[c] कोई पैरामीटर (वास्तविक फ़ंक्शन परिभाषा की तुलना में) के साथ फ़ंक्शन क्यों संकलित करता है?


Answers

सी func() मतलब है कि आप किसी भी तर्क को पारित कर सकते हैं। यदि आप कोई तर्क नहीं चाहते हैं तो आपको func(void) रूप में घोषित करना होगा। जिस प्रकार आप अपने फ़ंक्शन पर जा रहे हैं, अगर int को डिफ़ॉल्ट निर्दिष्ट नहीं किया गया है।

Question

मैं बस किसी के सी कोड में आया हूं कि मैं उलझन में हूं कि यह संकलन क्यों कर रहा है। दो बिंदु हैं जिन्हें मैं समझ नहीं पा रहा हूं।

सबसे पहले, फ़ंक्शन प्रोटोटाइप में वास्तविक फ़ंक्शन परिभाषा की तुलना में कोई पैरामीटर नहीं है। दूसरा, फ़ंक्शन परिभाषा में पैरामीटर में कोई प्रकार नहीं है।

#include <stdio.h>

int func();

int func(param)
{
    return param;
}

int main()
{
    int bla = func(10);    
    printf("%d", bla);
}

यह क्यों काम करता है? मैंने इसे कुछ कंपाइलर्स में परीक्षण किया है, और यह ठीक काम करता है।




सी फ़ंक्शन रिटर्न प्रकार और पैरामीटर सूची पर कोई प्रकार नहीं दिया गया है तो int मानता है । अजीब चीजें संभव होने के बाद ही इस नियम के लिए।

एक फ़ंक्शन परिभाषा इस तरह दिखती है।

int func(int param) { /* body */}

यदि यह एक प्रोटोटाइप है जिसे आप लिखते हैं

int func(int param);

प्रोटोटाइप में आप केवल पैरामीटर के प्रकार निर्दिष्ट कर सकते हैं। पैरामीटर्स का नाम अनिवार्य नहीं है। इसलिए

int func(int);

इसके अलावा यदि आप पैरामीटर प्रकार निर्दिष्ट नहीं करते हैं लेकिन नाम int को प्रकार के रूप में माना जाता है।

int func(param);

यदि आप आगे बढ़ते हैं, तो काम भी करते हैं।

func();

जब आप func() लिखते हैं तो कंपाइलर int func() मानता है। लेकिन फंक्शन बॉडी के अंदर func() डालें। वह एक फंक्शन कॉल होगा




यही कारण है कि मैं आम तौर पर लोगों को उनके कोड को संकलित करने की सलाह देता हूं:

cc -Wmissing-variable-declarations -Wstrict-variable-declarations -Wold-style-definition

ये झंडे कुछ चीजों को लागू करते हैं:

  • -विग्मित-परिवर्तनीय-घोषणाएं: पहले प्रोटोटाइप प्राप्त किए बिना एक गैर स्थैतिक फ़ंक्शन घोषित करना असंभव है। यह अधिक संभावना है कि एक हेडर फ़ाइल में प्रोटोटाइप वास्तविक परिभाषा के साथ मेल खाता है। वैकल्पिक रूप से, यह लागू करता है कि आप उन स्थिर कार्यों में स्थिर कीवर्ड जोड़ते हैं जिन्हें सार्वजनिक रूप से दिखाई देने की आवश्यकता नहीं है।
  • -Wstrict-variable-घोषणाएं: प्रोटोटाइप को तर्कों को सही ढंग से सूचीबद्ध करना होगा।
  • -वॉल्ड-स्टाइल-परिभाषा: फ़ंक्शन परिभाषा को स्वयं तर्कों को ठीक से सूचीबद्ध करना होगा।

इन झंडे का उपयोग कई ओपन सोर्स प्रोजेक्ट्स में डिफ़ॉल्ट रूप से भी किया जाता है। उदाहरण के लिए, फ्रीबीएसडी में आपके मेकफ़ाइल में WARNS = 6 के साथ निर्माण करते समय इन झंडे सक्षम हैं।




पैरामीटर प्रकार के संबंध में, यहां पहले से ही सही उत्तर हैं लेकिन यदि आप इसे कंपाइलर से सुनना चाहते हैं तो आप कुछ झंडे जोड़ने की कोशिश कर सकते हैं (झंडे लगभग हमेशा एक अच्छा विचार हैं)।

gcc foo.c -Wextra का उपयोग कर अपने प्रोग्राम को संकलित करना मुझे मिलता है:

foo.c: In function ‘func’:
foo.c:5:5: warning: type of ‘param’ defaults to ‘int’ [-Wmissing-parameter-type]

आश्चर्यजनक रूप से - -Wextra इसे -Wmissing-parameter-type लिए नहीं पकड़ता है (यह किसी कारण के लिए -Wmissing-parameter-type को पहचान नहीं सकता है, शायद ऊपर वर्णित ऐतिहासिक लोगों के लिए) लेकिन -pedantic करता है:

foo.c:5:10: warning: parameter 'param' was not declared, 
defaulting to type 'int' [-pedantic]
int func(param)
         ^
1 warning generated.

और प्रोटोटाइप मुद्दे के लिए जैसा कि int func() से ऊपर कहा गया है, मनमाने ढंग से पैरामीटर को संदर्भित करता है जब तक कि आप इसे स्पष्ट रूप से int func(void) रूप में परिभाषित नहीं करते हैं, जो आपको अपेक्षित त्रुटियों के रूप में परिभाषित करेगा:

foo.c: In function ‘func’:
foo.c:6:1: error: number of arguments doesn’t match prototype
foo.c:3:5: error: prototype declaration
foo.c: In function ‘main’:
foo.c:12:5: error: too many arguments to function ‘func’
foo.c:5:5: note: declared here

या clang रूप में:

foo.c:5:5: error: conflicting types for 'func'
int func(param)
    ^
foo.c:3:5: note: previous declaration is here
int func(void);
    ^
foo.c:12:20: error: too many arguments to function call, expected 0, have 1
    int bla = func(10);
              ~~~~ ^~
foo.c:3:1: note: 'func' declared here
int func(void);
^
2 errors generated.



  • खाली पैरामीटर सूची का अर्थ है "कोई तर्क", इसलिए परिभाषा गलत नहीं है।
  • लापता प्रकार int होना माना जाता है।

मैं किसी भी बिल्ड पर विचार करता हूं जो इसे कॉन्फ़िगर किए गए चेतावनी / त्रुटि स्तर में कमी के लिए गुजरता है, हालांकि वास्तविक कोड के लिए यह अनुमति देने में कोई बात नहीं है।




Related