2010-05-05 26 views
29

कुछ पुराने कोड है कि मैं सिर्फ भर में आया था:यह कोड अभी भी क्यों काम करता है?

MLIST * new_mlist_link() 
{ 
    MLIST *new_link = (MLIST *) malloc(sizeof(MLIST)); 
    new_link->next = NULL; 
    new_link->mapi = NULL; 
    new_link->result = 0; 
} 

यह किसी लिंक किए गए सूची बनाने के लिए बुलाया जा रहा है गया था, लेकिन मैंने देखा है कोई बयान नहीं है:,

return new_link; 
भी वापसी कथन के बिना वहाँ

सूची अभी भी ठीक से बनाया गया है। ऐसा क्यों हुआ?

संपादित करें: प्लेटफार्म: मैंड्रिवा 2009 64 बिट लिनक्स 2.6.24.7-सर्वर जीसीसी 4.2.3-6mnb1

संपादित करें: अजीब बात है ... इस कोड को भी सफलतापूर्वक के बारे में 5 अलग अलग लिनक्स प्रतिष्ठानों पर, भाग गया सब विभिन्न संस्करण/स्वाद, साथ ही एक मैक।

+2

वहाँ गूंगा भाग्य से अलग कोई संभावित जवाब है, जब तक (या शायद भले ही) आप हमें क्या मंच बताएं। – Potatoswatter

+1

यह एक स्थिर कोड चेकर का उपयोग करने के लिए एक अच्छा मामला बनाता है। – semaj

+3

दिलचस्प है कि यह कई प्लेटफार्मों पर चला। इसमें केवल एक स्थानीय चर है, इसलिए इंटेल पर ईसीसी (या इसके 64-बिट समतुल्य) में एक स्थानीय चर को स्टोर करने के लिए जीसीसी के लिए यह बहुत मानक होना चाहिए, और वापसी मूल्यों के लिए उस रजिस्टर का उपयोग करना भी आवश्यक है। –

उत्तर

35

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

यह वास्तव में करने के लिए गैर पोर्टेबल और बहुत खतरनाक है, लेकिन यह उन छोटी सी चीजों में से एक है जो सी में प्रोग्रामिंग को इतना मजेदार बनाता है।

+4

+1, इसके अतिरिक्त यह एबीआई है, न कि ऑपरेटिंग सिस्टम जो कॉलिंग सम्मेलन को परिभाषित करता है। – danben

+1

यह बताता है कि यह क्यों भाग गया, लेकिन यह संकलित क्यों हुआ अगला प्रश्न है। : पी आपको लगता है कि कंपाइलर रिटर्न स्टेटमेंट की जांच करेगा (मुझे पता है कि मेरा सब कुछ है)। किसी भी तरह से, यह काम करता है, यह निश्चित रूप से एक बुरा बात लेबल किया जा सकता है। – ssube

+1

मुझे लगता है कि कोडिंग की यह शैली 30 साल पहले अधिक आम थी जब सी लोकप्रिय हो रहा था। यह कोड जो इस कोड से आया था, शायद पुराने कोडर (या बस बहुत समय पहले) द्वारा लिखा गया था और तब से संकलक चेतावनियां अक्षम थीं ताकि यह सही ढंग से संकलित हो सके। –

5

यह मूल रूप से भाग्य है; स्पष्ट रूप से, संकलक एक ही स्थान पर new_link चिपकने के लिए होता है, यह एक लौटा मूल्य चिपक जाएगा।

-1

शायद एक संयोग:

समारोह की वापसी मूल्य के लिए अंतरिक्ष समय से आगे आवंटित किया जाता है। चूंकि वह मान अनियमित है, इसलिए यह संरचना के लिए आवंटित स्मृति के रूप में ढेर पर एक ही स्थान की ओर इशारा कर सकता था।

+1

उह, नहीं, लौटाए गए मूल्य आमतौर पर रजिस्टरों में लौटाए जाते हैं, या, मुझे लगता है, ढेर पर। यह एक यादृच्छिक सूचक नहीं है जो रहस्यमय रूप से सही है। वापसी मूल्य आवंटित नहीं किए जाते हैं। – WhirlWind

+1

जैसा ऊपर बताया गया है, यदि वे एक सूचक के मामले में फिट होते हैं तो वापसी मूल्यों को एक रजिस्टर में वापस कर दिया जाता है। – Joel

+4

@Whirl: कुछ आर्किटेक्चर पर, प्रक्रिया को लागू होने पर वापसी मूल्यों के लिए स्टैक पर स्थान आरक्षित होता है। दूसरों पर, परिणाम एक रजिस्टर में वापस कर दिया जाता है। यह अलग है**। –

1

यह संयोग से काम करता है। आपको उस पर भरोसा नहीं करना चाहिए।

7

संभावित यह केवल ईएक्स रजिस्टर का उपयोग करता है जो सामान्य रूप से अंतिम कार्य के वापसी मूल्य को संग्रहीत करता है। यह बिल्कुल अच्छा अभ्यास नहीं है! इस तरह की चीजों के लिए व्यवहार अपरिभाषित है .. लेकिन यह काम देखने के लिए अच्छा है ;-)

1

सबसे अधिक संभावना है कि यह बग खोजने के लिए बहुत कठिन उत्पादन करेगा। मुझे यकीन है कि मैंने इसे पढ़ा है, लेकिन मुझे याद है कि अगर आप रिटर्न स्टेटमेंट डालना भूल जाते हैं, तो अधिकांश कंपाइलर्स शून्य लौटने के लिए डिफ़ॉल्ट होंगे।

#include <iostream> 

using namespace std; 

int* getVal(); 

int main() 
{ 
     int *v = getVal(); 
     cout << "Value is: " << *v << endl; 
     return 0; 
} 

int* getVal() 
{ 
     // return nothing here 
} 

मेरे लिए, यह रूप में अच्छी तरह से काम करता है:

यहाँ एक छोटी उदाहरण है। हालांकि, जब मैं इसे चलाता हूं, तो मुझे सेगमेंट गलती मिलती है। तो यह वास्तव में अपरिभाषित है। सिर्फ इसलिए कि यह संकलित करता है, इसका मतलब यह नहीं होगा कि यह काम करेगा।

+1

वॉटसन मुझे लगता है? –

0

यह काम करता है क्योंकि 1 9 40 के दशक में जब सी भाषा बनाई गई थी, तो return कीवर्ड नहीं था।आप C43 Minsi मानक के "कार्यों" खंड में देखें, तो यह इस विषय पर कहने के लिए (अन्य बातों के साथ) है:

16.4.3b For backwards compatibility the EAX register MUST be used to return 
     the address of the first chunk of memory allocated by malloc. 

</humour>

+4

नहीं, यह नहीं है। कोई सी 43 मिनीएसआई मानक नहीं है, वह बस इसे बना रहा है। –

+0

अब हम सभी जेम्स के विनोद को जानते हैं। क्यों नीचे मतदान किया? – tristan

5

इस समस्या, उपयोग से बचने के लिए:

-Wreturn-type:

Warn whenever a function is defined with a return-type that defaults to int. Also warn about any return statement with no return-value in a function whose return-type is not void (falling off the end of the function body is considered returning without a value), and about a return statement with an expression in a function whose return-type is void.

-Werror=return-type एक त्रुटि में ऊपर चालू करने के लिए:

Make the specified warning into an error. The specifier for a warning is appended, for example -Werror=switch turns the warnings controlled by -Wswitch into errors. This switch takes a negative form, to be used to negate -Werror for specific warnings, for example -Wno-error=switch makes -Wswitch warnings not be errors, even when -Werror is in effect. You can use the -fdiagnostics-show-option option to have each controllable warning amended with the option which controls it, to determine what to use with this option.

(GCCs warning options से)

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