क्या चल रहा है, इस बारे में प्रश्न के मांस में जाने से पहले, यह बताना महत्वपूर्ण है कि दोष रिपोर्ट 1886 के अनुसार कार्यक्रम बीमार है : मुख्य के लिए भाषा लिंकेज () :
[...] एक प्रोग्राम जो वैश्विक दायरे में एक चर मुख्य घोषित करता है या जो सी भाषा लिंकेज (किसी भी नामस्थान में) के साथ मुख्य नाम घोषित करता है, बीमार है। [...]
क्लैंग और जीसीसी के सबसे हाल के संस्करण इसे एक त्रुटि बनाते हैं और कार्यक्रम संकलित नहीं करेगा ( जीसीसी लाइव उदाहरण देखें ):
error: cannot declare '::main' to be a global variable
int main = ( std::cout << "C++ is excellent!\n", 195 );
^
तो gcc और clang के पुराने संस्करणों में कोई डायग्नोस्टिक क्यों नहीं था? इस दोष रिपोर्ट में 2014 के अंत तक एक प्रस्तावित प्रस्ताव भी नहीं था और इसलिए यह मामला केवल हाल ही में स्पष्ट रूप से बीमार बना हुआ था, जिसे निदान की आवश्यकता है।
इससे पहले, ऐसा लगता है जैसे इस अपरिभाषित व्यवहार किया जाएगा, क्योंकि हम एक का उल्लंघन कर रहे करेगा मसौदा सी की आवश्यकता ++ अनुभाग से मानक 3.6.1
[basic.start.main] :
एक कार्यक्रम में मुख्य नामक एक वैश्विक फ़ंक्शन शामिल होगा, जो कार्यक्रम की निर्दिष्ट शुरुआत है। [...]
अपरिभाषित व्यवहार अप्रत्याशित है और इसके लिए नैदानिक की आवश्यकता नहीं है। जिस असंगति को हम व्यवहार को पुन: प्रस्तुत करते हुए देखते हैं वह विशिष्ट अपरिभाषित व्यवहार है।
तो वास्तव में कोड क्या कर रहा है और कुछ मामलों में यह परिणाम क्यों देता है? आइए देखें कि हमारे पास क्या है:
declarator
| initializer----------------------------------
| | |
v v v
int main = ( std::cout << "C++ is excellent!\n", 195 );
^ ^ ^
| | |
| | comma operator
| primary expression
global variable of type int
हम main
जो एक है पूर्णांक ग्लोबल नेम स्पेस में घोषित कर दिया और प्रारंभ की जा रही है, चर स्थिर भंडारण अवधि है। यह कार्यान्वित किया गया है कि क्या कॉल करने के प्रयास से पहले इनिशियलाइज़ेशन हो जाएगा main
लेकिन ऐसा लगता है कि कॉल करने से पहले ऐसा होता है main
।
कोड अल्पविराम ऑपरेटर का उपयोग करता है , बाएं ऑपरेंड एक त्याग मूल्य अभिव्यक्ति है और कॉलिंग के साइड इफेक्ट के लिए पूरी तरह से यहां उपयोग किया जाता है std::cout
। अल्पविराम ऑपरेटर का परिणाम सही ऑपरेंड है जो इस मामले में प्रचलन है 195
जो चर को सौंपा गया है main
।
हम सार्जेंट पॉइंट्स को असेंबली असेंबली शो के cout
दौरान देख सकते हैं जिसे स्टैटिक इनिशियलाइज़ेशन के दौरान कहा जाता है। हालाँकि चर्चा के लिए और अधिक दिलचस्प बिंदु लाइव गॉडबोल्ट सत्र यह होगा:
main:
.zero 4
और बाद में:
movl $195, main(%rip)
संभावित परिदृश्य यह है कि यह कार्यक्रम प्रतीक के लिए कूदता है जो main
वैध कोड होने की उम्मीद करता है और कुछ मामलों में सेग-गलती करेगा । तो अगर ऐसा है तो हम उम्मीद करेंगे कि वेरिएबल में मान्य मशीन कोड को स्टोर main
करने से काम करने योग्य प्रोग्राम बन सकता है , यह मानते हुए कि हम एक सेगमेंट में स्थित हैं जो कोड निष्पादन की अनुमति देता है। हम देख सकते हैं इस 1984 IOCCC प्रवेश करता है सिर्फ इतना है कि ।
ऐसा प्रतीत होता है कि हम सी का उपयोग करके इसे प्राप्त कर सकते हैं ( इसे लाइव देखें ):
const int main = 195 ;
यदि यह वस्तुतः चर main
नहीं है तो यह सह-दोष है क्योंकि यह एक निष्पादन योग्य स्थान पर स्थित नहीं है, यहां टिप टिप इस टिप्पणी के लिए है जिसने मुझे यह विचार दिया।
इस प्रश्न के C विशिष्ट संस्करण के लिए यहां भी FUZxxl उत्तर देखें ।