2008-09-16 7 views
6

कंपाइलर नींद समारोह या यहां तक ​​कि printf फ़ंक्शन के प्रोटोटाइप को कैसे जानता है, जब मैंने पहली जगह में कोई हेडर फ़ाइल शामिल नहीं की थी?हम एक संकलन समय त्रुटि क्यों नहीं प्राप्त करते हैं भले ही हम एक सी प्रोग्राम में stdio.h शामिल नहीं करते हैं?

इसके अलावा, अगर मैं sleep(1,1,"xyz") या किसी भी मनमाने ढंग से तर्कों को निर्दिष्ट करता हूं, तो संकलक अभी भी इसे संकलित करता है। लेकिन अजीब बात यह है कि जीसीसी लिंक समय पर इस फ़ंक्शन की परिभाषा को खोजने में सक्षम है, मुझे समझ में नहीं आता कि यह कैसे संभव है, क्योंकि वास्तविक sleep() फ़ंक्शन केवल एक ही तर्क लेता है, लेकिन हमारे कार्यक्रम ने तीन तर्कों का उल्लेख किया है।

/********************************/ 
int main() 
{ 
short int i; 
for(i = 0; i<5; i++) 
{ 
    printf("%d",i);`print("code sample");` 
    sleep(1); 
} 
return 0; 
} 

उत्तर

2

सी अज्ञात प्रकारों के लिए int अनुमान लगाएगा। तो, शायद यह सोचता है कि नींद में यह प्रोटोटाइप है:

int sleep(int); 

एकाधिक पैरामीटर और लिंकिंग देने के लिए ... मुझे यकीन नहीं है। यह मुझे आश्चर्यचकित करता है। अगर वह वास्तव में काम करता है, तो रन-टाइम पर क्या हुआ?

1

कंपाइलर पर निर्भर करता है, लेकिन जीसीसी के साथ (उदाहरण के लिए, क्योंकि यह वह है जिसे आपने संदर्भित किया है), कुछ मानक (दोनों सी और पॉज़िक्स) कार्यों ने "कंपाइलर इंट्रिनिक्स" बनाया है। इसका मतलब है कि आपके कंपाइलर के साथ भेजे गए कंपाइलर लाइब्रेरी (इस मामले में libgcc) में फ़ंक्शन का कार्यान्वयन होता है। कंपाइलर एक निहित घोषणा (यानी, शीर्षलेख के बिना फ़ंक्शन का उपयोग करके) की अनुमति देगा, और लिंकर को कंपाइलर लाइब्रेरी में कार्यान्वयन मिलेगा क्योंकि आप संभवतः एक लिंकर फ्रंट-एंड के रूप में कंपाइलर का उपयोग कर रहे हैं।

अपनी ऑब्जेक्ट को '-c' ध्वज (केवल संकलित करें, कोई लिंक नहीं) के साथ संकलित करने का प्रयास करें, और उसके बाद सीधे लिंकर का उपयोग करके उन्हें लिंक करें। आप पाएंगे कि आपको लिंकर त्रुटियां मिलती हैं जिन्हें आप उम्मीद करते हैं।

वैकल्पिक रूप से, जीसीसी इंट्रिनिक्स के उपयोग को अक्षम करने के विकल्पों का समर्थन करता है: -fno-builtin या दानेदार नियंत्रण के लिए, -fno-builtin-function। ऐसे कुछ विकल्प हैं जो उपयोगी हो सकते हैं यदि आप होमब्री कर्नेल या किसी अन्य प्रकार के ऑन-द-मेटल ऐप बनाने जैसे कुछ कर रहे हैं।

10

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

सीपीयू आर्किटेक्चर तर्कों के आधार पर रजिस्ट्रारों में प्रवेश किया जा सकता है (उदाहरण के लिए, एमआईपीएस पर ए 3 के माध्यम से ए0) या मूल x86 कॉलिंग सम्मेलन में उन्हें स्टैक पर दबाकर। किसी भी मामले में, अतिरिक्त तर्क पारित करना हानिरहित है। बुलाया गया फ़ंक्शन पास किए गए रजिस्टरों का उपयोग नहीं करेगा और न ही स्टैक पर अतिरिक्त तर्कों का संदर्भ देगा, लेकिन कुछ भी बुरा नहीं होता है।

कम तर्कों में उत्तीर्ण करना अधिक समस्याग्रस्त है। बुलाया गया फ़ंक्शन उचित रजिस्टर या स्टैक स्थान में होने वाली कचरा का उपयोग करेगा, और हाइजिंग हो सकता है।

+0

कहा जाता है कि वहाँ कॉलिंग सम्मेलन है जहां कॉल किए गए फ़ंक्शन को ढेर को साफ करने की आवश्यकता होती है, जो गलत संख्या की संख्या में नहीं कर सकती है, या ग़लत आकार के तर्क कॉलर द्वारा ढेर पर धकेल गए – nos

5

क्लासिक सी में, आपको फ़ंक्शन को कॉल करने के लिए प्रोटोटाइप की आवश्यकता नहीं है। कंपाइलर अनुमान लगाएगा कि फ़ंक्शन एक int देता है और पैरामीटर की अज्ञात संख्या लेता है। यह कुछ आर्किटेक्चर पर काम कर सकता है, लेकिन यह विफल हो जाएगा यदि फ़ंक्शन int की तरह कुछ, संरचना की तरह कुछ देता है, या यदि कोई पैरामीटर रूपांतरण होता है।

अपने उदाहरण में, नींद में देखा जाता है और संकलक की तरह

int sleep(); 

नोट एक प्रोटोटाइप है कि तर्क सूची खाली है मान लिया गया है। सी में, यह शून्य के समान नहीं है। यह वास्तव में "अज्ञात" का मतलब है।आप कश्मीर & आर सी कोड लिख रहे थे, तो आप की तरह

int sleep(t) 
int t; 
{ 
    /* do something with t */ 
} 

कोड के माध्यम से अज्ञात पैरामीटर हो सकता था यह सभी खतरनाक है विशेष रूप से कुछ एम्बेडेड चिप्स जहां रास्ता मापदंडों एक प्रोटोटाइप के साथ एक से अलग है एक unprototyped समारोह के लिए पारित कर रहे हैं पर ।

नोट: लिंक करने के लिए प्रोटोटाइप की आवश्यकता नहीं है। आमतौर पर, लिंकर स्वचालित रूप से सी रनटाइम लाइब्रेरी से लिंक करता है जैसे कि लिनक्स पर ग्लिबैक। नींद के उपयोग और कोड जो लागू होता है, के बीच संबंध स्रोत कोड संसाधित होने के बाद लिंक समय पर होता है।

मैं सुझाव दूंगा कि आप इस तरह की समस्याओं से बचने के लिए प्रोटोटाइप की आवश्यकता के लिए अपने कंपाइलर की सुविधा का उपयोग करें। जीसीसी के साथ, यह -स्ट्रिक्ट-प्रोटोटाइप कमांड लाइन तर्क है। कोडवायरियर टूल्स में, यह सी/सी ++ कंपाइलर पैनल में "प्रोटोटाइप की आवश्यकता" ध्वज था।

1

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

2

यह 'के & आर सी' और 'एएनएसआई सी' नामक किसी चीज़ के साथ करना है। अच्छे पुराने के & आर सी में, अगर कुछ घोषित नहीं किया गया है, तो यह int माना जाता है। तो कोई भी चीज़ जो फ़ंक्शन कॉल की तरह दिखती है, लेकिन फ़ंक्शन के रूप में घोषित नहीं की गई है, स्वचालित रूप से 'int' और तर्क प्रकारों का वापसी मूल्य पर आधारित होगा।

हालांकि बाद में लोगों ने यह पता लगाया कि यह कभी-कभी बहुत खराब हो सकता है। तो कई कंपाइलर्स ने चेतावनी दी। सी ++ ने यह त्रुटि बनाई। मुझे लगता है कि जीसीसी के पास ध्वज (-निक या चिकित्सकीय?) है, जो इस स्थिति को एक त्रुटि बनाता है।

तो, संक्षेप में, यह ऐतिहासिक सामान है।

2

अन्य उत्तरों संभावित मैकेनिक्स को कवर करते हैं (सभी अनुमान संकलक निर्दिष्ट नहीं हैं)।

आपके पास यह मुद्दा यह है कि आपका संकलक और लिंकर प्रत्येक संभावित त्रुटि और चेतावनी को सक्षम करने के लिए सेट नहीं किया गया है। किसी भी नई परियोजना के लिए ऐसा करने के लिए (वास्तव में) कोई बहाना नहीं है। विरासत परियोजनाओं के लिए अधिक बहाना - लेकिन जितना संभव हो सके

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