2011-05-31 12 views
19

int foo = foo; संकलन के लिए मानक संदर्भ। सी ++ मानक का कौन सा हिस्सा इस अनुमति देता है?int foo = foo

+0

संबंधित: http://stackoverflow.com/questions/5450633/c-what-does-this-mean-int-foo-foo-4 –

+0

यह भी देखें [प्रारंभिकता में लवल-टू-रावल्यू रूपांतरण शामिल है? क्या 'int x = x; 'UB?] (Http://stackoverflow.com/q/14935722/1708801) और [सी ++ मानक में अनिश्चित मानों और अपरिभाषित व्यवहार के उपयोग के संबंध में सी ++ मानक बदल गया है?] (http://stackoverflow.com/q/23415661/1708801) –

उत्तर

26

3.3.1 प्वाइंट [basic.scope.pdecl]

एक नाम के लिए घोषणा की बात तुरंत अपनी पूर्ण declarator (खंड 8) के बाद और उसके प्रारंभकर्ता से पहले (यदि हो तो),

है

घोषणा अच्छी तरह परिभाषित है यदि घोषणा फ़ाइल दायरे पर है। यदि आपके पास फ़ंक्शन स्कोप पर घोषणा है और यदि आप बाद में foo का उपयोग करते हैं [जिसे उस मामले में कुछ अनिर्दिष्ट मूल्य के लिए प्रारंभ किया जाएगा] व्यवहार को अपरिभाषित किया जाएगा।

+4

मैं +1 लेकिन आप पूरी तरह से है कि ओपी कार्यक्रम व्यवहार अपरिभाषित है और used_ नहीं किया जा _should उल्लेख करने में विफल कर दिया है होगा। –

+5

@Tomalak: कोड * हो सकता है * यूबी है, लेकिन जरूरी नहीं है। ओ पी पूरी तरह से पता है कि यह कुछ ऐसा है जो वास्तव में इस्तेमाल किया जाना चाहिए नहीं है लगता है, और क्यों यह सब पर संकलित की विशुद्ध रूप से शैक्षिक बिंदु के बारे में उत्सुक है। –

+2

@ जेरी: परी नफ। –

21

यह?

int main() { 
    int foo = foo; 
} 

वस्तु foo= के बाद मौजूद है, [basic.scope.pdecl] के अनुसार:

एक नाम के लिए घोषणा की बात के ठीक बाद में अपनी पूर्ण declarator (खंड 8) और अपने प्रारंभकर्ता से पहले (यदि कोई है)।

हालांकि, एक पूरे के रूप कार्यक्रम, अपरिभाषित है, क्योंकि आप (आरएचएस पर) का उपयोग एक uninitialised मूल्य:

int x = x; यहाँ [..] x अपने स्वयं के (अनिश्चित) के साथ आरंभ नहीं हो जाता मूल्य।

और:

हालांकि "अनुमानित और बीमार निर्दिष्ट" मानक, an lvalue-to-rvalue conversion is performed on the RHS expression foo द्वारा।

और ([conv.lval]):

एक गैर समारोह का एक lvalue (3.10), गैर सरणी प्रकार टी एक rvalue करने के लिए परिवर्तित किया जा सकता है। यदि टी एक अपूर्ण प्रकार है, एक प्रोग्राम जो इस रूपांतरण की आवश्यकता है, वह खराब है। वस्तु जो करने के लिए संदर्भित करता है lvalue प्रकार टी का एक उद्देश्य नहीं है और एक प्रकार टी से प्राप्त की एक वस्तु, या अगर वस्तु अप्रारंभीकृत है, नहीं है, तो एक कार्यक्रम कि इस रूपांतरण जरूरी अपरिभाषित व्यवहार है ।

उचित चेतावनी स्तर के साथ, you will get told about it; हालांकि, अपरिभाषित व्यवहार का आह्वान करने वाले कार्यक्रमों को संकलित करने की अनुमति है। जब आप उन्हें चलाते हैं तो वे कुछ भी कर सकते हैं।


या, इसके बारे में क्या?

int foo = foo;  
int main() {} 

ध्यान दें कि foo एक "वैश्विक" है। ये [basic.start.init] के अनुसार शून्य initialised पहले कदम के रूप कर रहे हैं,:

स्थिर भंडारण अवधि (3.7.1) के साथ वस्तुओं की जाएगी से पहले किसी अन्य प्रारंभ जगह लेता है शून्य प्रारंभ (8.5)

तो आपको int foo मूल्य 0 के साथ मिलेगा; इसकी वैधता की, इस बिंदु पर, प्रति [basic.scope.pdecl] के रूप में ऊपर है, और के रूप में प्रति [stmt.decl]:

स्थिर भंडारण अवधि के साथ सभी स्थानीय वस्तुओं की शून्य प्रारंभ (8,5) (3.7.1) किसी भी पहले किया जाता है अन्य प्रारंभिक स्थान होता है। [..]

फिर आप यह foo (ही) के लिए मूल्य-आरंभ ... अर्थात 0.

यह अच्छी तरह से परिभाषित किया गया है, अगर एक छोटे से गुप्त।


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

int foo = 42; 
int main() { 
    int foo = foo; 
} 

दुःख की बात है this is the same as the first case। चूंकि स्थानीय foo पहले ही घोषित किया गया है और जब प्रारंभकर्ता का मूल्यांकन किया जाता है तब तक दायरे में, प्रारंभकर्ता स्थानीय foo का उपयोग करता है और आप अभी भी अपरिभाषित व्यवहार से फंस गए हैं। वैश्विक foo का उपयोग नहीं किया जाता है। घोषणा के

+1

ओटीओएच, यदि यह वैश्विक है, तो व्यवहार परिभाषित किया गया है। –

+0

@ जेरी: मेरे कार्यक्रम में कोई ग्लोबल्स नहीं हैं। यदि ओपी के कार्यक्रम में ग्लोबल्स हैं (या यदि उनकी 'foo' घोषणा नामस्थान स्कोप पर होती है), तो उन्हें यह बताना होगा क्योंकि यह पूरी तरह से प्रश्न को बदलता है। –

+0

@ जेरी: ठीक है। मैं उस मामले के लिए भी एक खंड जोड़ दूंगा। –

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