2008-12-03 22 views
24

सत्र प्रतिलेख:क्यों #को printf() का उपयोग करने की आवश्यकता नहीं है?

>type lookma.c 
int main() { 
    printf("%s", "no stdio.h"); 
} 

>cl lookma.c 
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.762 for 80x86 
Copyright (C) Microsoft Corporation. All rights reserved. 

lookma.c 
Microsoft (R) Incremental Linker Version 8.00.50727.762 
Copyright (C) Microsoft Corporation. All rights reserved. 

/out:lookma.exe 
lookma.obj 

>lookma 
no stdio.h 
+0

ध्यान दें कि सी 8 9/सी 0 9 0 में, आपको 'मुख्य()' सी 99 से रिटर्न वैल्यू की आपूर्ति करनी चाहिए, आपको 'रिटर्न 0;' या 'मुख्य() ' –

उत्तर

28

सख्त अनुपालन मोड (जिसका अर्थ है "सिद्धांत में") में, आप अपरिभाषित व्यवहार (जो खराब है) का आह्वान करते हैं, जब आप एक फ़ंक्शन को कॉल करते हैं जो स्कोप में फ़ंक्शन की प्रोटोटाइप घोषणा के बिना तर्कों की एक चर संख्या लेता है। इसका मतलब है कि संकलक को किसी प्रोग्राम के साथ कुछ भी करने की अनुमति है जो printf() का उपयोग #include <stdio.h> या समकक्ष घोषणा से प्रोटोटाइप के बिना करता है। "जो कुछ भी इसे पसंद करता है" में विकल्पों में से एक के रूप में सही ढंग से काम करना शामिल है; ऐसा लगता है कि आपके उदाहरण द्वारा चुना गया विकल्प है।

प्रैक्टिस में, कोड printf() फ़ंक्शन की औपचारिक घोषणा के बिना भी अधिकांश व्यावहारिक कंपाइलरों के साथ ठीक काम करेगा।

जैसा कि qrdl द्वारा इंगित किया गया था, फ़ंक्शन पाया गया क्योंकि सी कंपाइलर सी लाइब्रेरी के साथ लिंक करता है।

ध्यान दें कि क्रिस यंग की सी 99 और 'अंतर्निहित int' के बारे में टिप्पणी सटीक है, लेकिन 'परिवर्तनीय तर्क कार्यों के बारे में नियम में स्कोप में प्रोटोटाइप होना चाहिए' C89 और C99 दोनों पर लागू होता है। अधिकांश कंपाइलर डिफ़ॉल्ट रूप से सख्त सी 99 संगतता मोड में काम नहीं करते हैं क्योंकि बहुत अधिक कोड है जो इस तरह संकलित नहीं होगा।

क्रिस युवा टिप्पणी की:

स्पष्ट करने के लिए, मेरी टिप्पणी निहित घोषणाओं को हटाने C99 पर था। "निहित int" कहकर, मुझे लगता है कि आप foo (शून्य) जैसी घोषणाओं की अनुमति देने की C89 सुविधा का जिक्र कर रहे हैं; int foo (शून्य) का मतलब है, कुछ सी 99 भी हटा दिया गया है।

क्रिस, ज़ाहिर है, सही है। सी 99 मानक से हटाए गए दो 'निहित घोषणा' विशेषताएं थीं।मानक के प्राक्कथन उन्हें सूचीबद्ध करता है के रूप में:

  • निहित int
  • को दूर हटाने के निहित समारोह घोषणा

मैं नहीं सोच रहा था (और इसलिए नहीं लिख) स्पष्ट रूप से पर्याप्त। फिर भी, सी 8 9 और सी 99 दोनों कार्यों के लिए एक प्रोटोटाइप की आवश्यकता होती है जो तर्कों की एक परिवर्तनीय संख्या लेती है।

इसे समझने के लिए:

extern int pqr(); 
int main(void) 
{ 
    int i = pqr(1, 3); 
    return i; 
} 

पहली पंक्ति के बिना, यह एक समारोह है कि एक पूर्णांक (अनिर्दिष्ट तर्क के साथ) रिटर्न के रूप में कार्य pqr() का एक अंतर्निहित घोषणा के साथ एक सही C89 टुकड़ा है। यदि पहली पंक्ति extern pqr(); द्वारा प्रतिस्थापित की गई है, तो यह pqr() की एक स्पष्ट घोषणा के साथ एक सही C89 खंड है जो एक पूर्णांक (अनिर्दिष्ट तर्क के साथ) देता है, लेकिन वापसी का प्रकार 'अंतर्निहित int' है। जैसा लिखा है, फ़ंक्शन स्पष्ट रूप से घोषित किया गया है और इसमें एक स्पष्ट int रिटर्न प्रकार है - लेकिन इसमें अभी भी अनिर्दिष्ट तर्क हैं। मेरा मानना ​​है कि वैध सी 99 है - हालांकि पूरी तरह से वांछनीय नहीं है। निश्चित रूप से, जीसीसी (3.4.4) इसे '-std=c99 -pedantic' विकल्पों के साथ स्वीकार करता है। आदर्श रूप से, फ़ंक्शन घोषणा में पूर्ण प्रोटोटाइप शामिल होना चाहिए। (और, यदि pqr() को इलिप्सिस के साथ परिभाषित किया गया था, तो प्रोटोटाइप को सिद्धांत में आवश्यक होगा!)

+0

स्पष्ट करने के लिए, मेरी टिप्पणी सी 99 पर अंतर्निहित विचलन को हटा रही थी। "अंतर्निहित int" कहकर, मुझे लगता है कि आप foo जैसे घोषणाओं की अनुमति देने के C89 सुविधा का जिक्र कर रहे हैं (शून्य); int foo (शून्य) का मतलब है, कुछ सी 99 भी हटा दिया गया। – Chris

35

आप मूल रूप से इस सी ++ में चिह्नित किया था, लेकिन यह एक सी कार्यक्रम प्रतीत होता। यदि स्कोप में कोई प्रोटोटाइप नहीं है तो सी स्वचालित रूप से फ़ंक्शन के लिए एक निहित घोषणा प्रदान करेगा (जैसे <stdio.h> के समाप्ति के कारण)। अंतर्निहित घोषणा होगा:

int printf(); 

मतलब कि printf एक समारोह है कि एक पूर्णांक देता है और तर्क के किसी भी संख्या ले सकता है। यह प्रोटोटाइप आपके कॉल के लिए काम करने के लिए हुआ। आप # शामिल करना चाहिए <stdio.h>

अंत में, मैं जोड़ने चाहिए वर्तमान सी मानक (आईएसओ/आईईसी 9899: 1999 या बोलचाल की भाषा "C99") करता है नहीं निहित घोषणाओं की अनुमति देते हैं, और इस कार्यक्रम के अनुरूप नहीं हैं । लागू घोषणा हटा दी गई थी। मेरा मानना ​​है कि आपका कंपाइलर सी 99 का समर्थन नहीं करता है। सी ++ को भी सही प्रोटोटाइप की आवश्यकता होती है और यह निहित घोषणा नहीं करता है।

8

printf() मानक सी लाइब्रेरी में स्थित है और लिंकर हमेशा आपके निष्पादन योग्य को मानक लाइब्रेरी लिंक करता है, इसलिए कोई मानक फ़ंक्शन मिलेगा और कोई लिंकिंग समस्या नहीं होगी।

प्रोटोटाइप का उपयोग करने में उचित शीर्षलेख परिणामों को शामिल करने में विफलता जो समस्याएं पैदा कर सकती है, क्योंकि सी कंपाइलर मानता है कि प्रोटोटाइप रिटर्न के बिना फ़ंक्शन int देता है और तर्कों की चर संख्या लेता है। तो हमेशा हेडर शामिल करें - यह आपकी सुरक्षा बाड़ है।

+2

के अंत से समकक्ष' एक 'वैरिएबल नंबर' तर्कों की 'लेकिन एक अपरिभाषित-लेकिन-निश्चित संख्याओं के तर्क। –

संबंधित मुद्दे