मुख्य यहाँ 0 क्यों नहीं लौटता है?


116

मैं सिर्फ पढ़ रहा था

आईएसओ / आईईसी 9899: 201x समिति ड्राफ्ट - 12 अप्रैल, 2011

जिसमें मुझे 5.1.2.2.3 कार्यक्रम समाप्ति के तहत मिला

..reaching the } that terminates the main function returns a value of 0. 

इसका मतलब यह है कि यदि आप किसी भी रिटर्न स्टेटमेंट को निर्दिष्ट नहीं करते हैं main() , और यदि प्रोग्राम सफलतापूर्वक चलता है, तो मुख्य के समापन ब्रेस पर) 0 वापस आ जाएगा।

लेकिन निम्नलिखित कोड में मैं कोई रिटर्न स्टेटमेंट निर्दिष्ट नहीं करता, फिर भी यह 0 पर वापस नहीं आता है

#include<stdio.h>
int sum(int a,int b)
{
return (a + b);
}

int main()
{
    int a=10;
    int b=5;
    int ans;    
    ans=sum(a,b);
    printf("sum is %d",ans);
}

संकलन

gcc test.c  
./a.out
sum is 15
echo $?
9          // here it should be 0 but it shows 9 why?

69
+1 चश्मा पढ़ने के लिए धैर्य रखने के लिए .....
अशर

16
gccअपने आप में (संस्करण ४.२.२ के लिए) एक भाषा को बहुत समान रूप से संकलित करता है, लेकिन सी की तरह काफी नहीं है। यह ग्नू - ९ को संकलित करता है - एक भाषा "शिथिल" सी। ९ 4.6 पर आधारित है।
pmg

2
returnकथन पर कोष्ठक sum()अनावश्यक हैं। int main()होना चाहिए int main(void)
कीथ थॉम्पसन

24
भ्रम! = टाइपो। मेरे कीबोर्ड पर '0' और 'ओ' इसके काफी करीब हैं ताकि बाद में आसानी से हो सके। ;-)
The111

2
IMHO एक बहुत ही मूर्खतापूर्ण विनिर्देश है, क्योंकि यह संकलक को "मुख्य" फ़ंक्शन को एक विशेष तरीके से "निहित 0" जोड़कर प्रबंधित करने के लिए मजबूर करता है। तो "मुख्य" नाम का एक फ़ंक्शन थोड़ा अलग तरीके से व्यवहार करता है। संकलन-समय के चेक ("नो रिटर्न वैल्यू" के समान) के बारे में क्या?
ग्यूसेप गुएरिनि

जवाबों:


141

यह नियम सी मानक के 1999 संस्करण में जोड़ा गया था। C90 में, दी गई स्थिति अपरिभाषित है।

आप इसे -std=c99gcc में पास करके सक्षम कर सकते हैं ।

एक साइड नोट के रूप में, दिलचस्प 9 को लौटाया गया है क्योंकि यह वापसी है printfजिसमें से सिर्फ 9 अक्षर लिखे गए हैं।


40
या आप बस return 0;समापन से पहले जोड़ सकते हैं }। यह हानिरहित है और आपके प्रोग्राम को पुराने संकलक को पोर्टेबल बनाता है।
कीथ थॉम्पसन

2
@ Mr.32: अच्छा अवलोकन, प्रिंटफ () स्ट्रिंग की लंबाई लौटाता है, इसलिए यह 9 है जो कि मुख्य ("-dd = c99 का उपयोग किए बिना)" वापसी "है।
हिचम

1
@cnicutar: कार्य आम तौर पर स्टैक पर छोटे मान नहीं लौटाते हैं - क्योंकि इसमें एक चाल और एक वापसी के बजाय एक पॉप, एक धक्का और एक कूद शामिल होगा - इसलिए यह लगभग निश्चित रूप से एक रजिस्टर है, eaxविशेष रूप से x86 पर।
जॉन पर्सी

8
हां, x86 एपीआई आमतौर पर eaxरजिस्टर के माध्यम से पूर्णांक जैसे मान लौटाता है । अधिक जानकारी के लिए en.wikipedia.org/wiki/X86_calling_conventions#cdecl देखें ।
सिल्वेन डेफ्रेसने

2
कई बार मैंने "int foo (void) {bar ();}" जैसे कोड देखे हैं, जहां "return bar ()" का इरादा था। यह कोड स्पष्ट बग के बावजूद, अधिकांश प्रोसेसर पर ठीक काम करता है।
19

15

यह रिटर्न वैल्यू देता है printfजिसकी संख्या वास्तव में छपे हुए पात्रों की संख्या है।


सवाल इस बात पर बात नहीं करता है कि प्रोग्राम को निष्पादित करने वाले कंसोलव्यू में क्या छपा है, यह प्रोग्राम के रिटर्न वैल्यू के बारे में बात करता है: (आप इसे स्कैंड कमांड के साथ लिनक्स में प्राप्त कर सकते हैं: इको $? और विन्डोज़ में: इको% एररवेवल%? )
हिचम

1
@eharvest हालांकि मुझे नहीं पता है कि %errorlevel%विंडोज में कैसे चेक करें , बाहर निकलें कोड और mainलिनक्स में वापसी मूल्य के बीच कोई अंतर है ?
Summer_More_More_Tea

1
@ ईवेस्टवर्क: उत्तर इस बारे में बात नहीं करता है कि कंसोल में क्या मुद्रित है। यह वापसी के मूल्य के बारे में बात करता है, printfजो इस मामले में 9 है जो तब mainकुछ जीसीसी संस्करणों का उपयोग करते समय किसी भी तरह से बाहर निकलने के कोड के रूप में "पदोन्नत" हो जाता है ।
आह

माफ़ करना। मेरी गलती। तुम सही हो। मैंने यह उत्तर बहुत तेजी से पढ़ा: /
हिचम

1
ध्यान दें कि यह गारंटी नहीं है । C89 / C90 में, इस मामले में लौटा हुआ दर्जा अपरिभाषित है ; यह कुछ भी हो सकता है। यह 9 वापस करने के लिए होता है क्योंकि कंपाइलर ने कुछ और वापस करने का कोई प्रयास नहीं किया। अन्य संकलक संभवतः अलग व्यवहार करेंगे।
कीथ थॉम्पसन

6

एक फ़ंक्शन से रिटर्न वैल्यू को आमतौर पर सीपीयू के ईएक्सएक्स रजिस्टर में संग्रहीत किया जाता है, इसलिए कथन "रिटर्न 4;" आमतौर पर संकलन करेगा

mov eax, 4;
ret;

और वापसी x (आपके कंपाइलर के आधार पर) कुछ इस तरह होगी:

mov eax, [ebp + 4];
ret;

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

यह एक सरलीकृत स्पष्टीकरण है, विभिन्न कॉलिंग कन्वेंशन और लक्ष्य प्लेटफ़ॉर्म एक महत्वपूर्ण भूमिका निभाएंगे, लेकिन यह स्पष्ट करने के लिए पर्याप्त जानकारी होनी चाहिए कि आपके उदाहरण में 'पर्दे के पीछे' क्या हो रहा है।

यदि आपको असेंबलर की बुनियादी समझ मिल गई है, तो यह अलग-अलग कंपाइलरों के डिस्सैड की तुलना करने के लायक है। आप पा सकते हैं कि कुछ संकलक ईगल रजिस्टर को एक सुरक्षा के रूप में साफ़ कर रहे हैं।


11
संकलक ऐसा कर सकता है। यह अपरिभाषित है। इसके बजाय यह आपको प्रिंटर कारतूस के साथ सिर में गोली मारना चुन सकता है।
हल्की दौड़ ऑर्बिट

@LightnessRacesinOrbit अपरिभाषित अप्रत्याशित के समान नहीं है, अर्थात "यदि कंपाइलर X करता है, तो यह मानक अनुरूप होगा" यह तार्किक रूप से "कंपाइलर X को नहीं कर सकता है" का अनुसरण करता है
Owen

@ ओवेन: इसे परिभाषित करने वाला मानक मार्ग उद्धरण।
लाइटवेट रेस

2
@LightnessRacesinOrbit मुझे खेद है कि मैं काफी अनुसरण नहीं करता। मुझे लगता है कि मैं वास्तव में जो कहना चाहता हूं वह यह है कि मुझे लगता है कि इस उत्तर में प्रदान की गई हॉग इनसाइट्स जैसे कि नोगिन 182 डिबगिंग के लिए अविश्वसनीय रूप से उपयोगी हैं। जब आपका कार्यक्रम अप्रत्याशित परिणाम दे रहा है, तो बहुत बार आपको पता नहीं होता है कि वे कहां से आ रहे हैं या यहां तक ​​कि कोड में कहां देखना है, और कार्यान्वयन विवरण की समझ होने से आप सही दिशा में संकेत कर सकते हैं।
ओवेन

@ तब मैंने कभी दावा नहीं किया
ऑर्बिट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.