2012-10-19 5 views
13

मानक मतलब है एक चर की परिभाषा की संख्या पर कोई प्रतिबंध नहीं है कि अगर यह नहीं है लगता है ओडीआर रूप से प्रयुक्त (§3.2/3):यदि मैं एक चर का उपयोग नहीं करता हूं, तो क्या मेरे पास अनुवाद इकाइयों में इसकी कई परिभाषाएं हो सकती हैं?

हर कार्यक्रम के ठीक एक परिभाषा शामिल होगा प्रत्येक गैर-इनलाइन फ़ंक्शन या वेरिएबल जो उस प्रोग्राम में ओडीआर-प्रयुक्त होता है; कोई निदान की आवश्यकता नहीं है।

यह कहा गया है कि किसी भी चर एक अनुवाद इकाई (§3.2/1) के अंतर्गत कई बार परिभाषित नहीं किया जा सकता है:

कोई अनुवाद इकाई किसी भी चर के एक से अधिक परिभाषा शामिल होगा, समारोह , वर्ग प्रकार, गणना प्रकार, या टेम्पलेट।

लेकिन मुझे पूरे कार्यक्रम में गैर-ओड-प्रयुक्त चर के लिए प्रतिबंध नहीं मिल रहा है। तो मैं निम्नलिखित की तरह कुछ क्यों संकलन नहीं कर सकते हैं:

// other.cpp 
int x; 

// main.cpp 
int x; 
int main() {} 

संकलन और जी ++ 4.6.3 के साथ इन फ़ाइलों को जोड़ने, मैं multiple definition of 'x' के लिए एक लिंकर त्रुटि मिलती है। ईमानदार होने के लिए, मैं इसकी अपेक्षा करता हूं, लेकिन x कहीं भी ओडीआर-प्रयुक्त नहीं है (जहां तक ​​मैं कह सकता हूं), मैं नहीं देख सकता कि मानक इसे कैसे प्रतिबंधित करता है। या यह अनिर्धारित व्यवहार है?

उत्तर

11

आपका प्रोग्राम लिंक नियमों का उल्लंघन करता है। सी ++ 11 §3.5 [मूलभूत।कड़ी]/9 राज्यों:

दो ऐसे नाम हैं जो एक ही हैं और कहा कि अलग-अलग दायरों निरूपित करेगा ही चर, समारोह, प्रकार, प्रगणक, टेम्पलेट या नाम स्थान घोषित किये गए हैं, तो

  • दोनों नामों में बाहरी संबंध होता है या अन्य दोनों नामों में आंतरिक संबंध होता है और उसी अनुवाद इकाई में घोषित किया जाता है; और

  • दोनों नाम समान नामस्थान के सदस्यों या सदस्यों के लिए संदर्भित करते हैं, न कि एक ही कक्षा के विरासत से; और

  • जब दोनों नाम फ़ंक्शंस को इंगित करते हैं, तो फ़ंक्शन की पैरामीटर-प्रकार-सूचियां समान होती हैं; और

  • जब दोनों नाम फ़ंक्शन टेम्पलेट्स को इंगित करते हैं, तो हस्ताक्षर समान होते हैं।

(मैं संदर्भ के लिए पूरा पैराग्राफ उल्लेख किया है। दूसरा दो गोलियों यहां लागू नहीं होते।)

अपने कार्यक्रम में, दो नाम x, जो एक ही कर रहे हैं देखते हैं। उन्हें विभिन्न क्षेत्रों में घोषित किया जाता है (इस मामले में, उन्हें विभिन्न अनुवाद इकाइयों में घोषित किया जाता है)। दोनों नामों में बाहरी संबंध है और दोनों नाम एक ही नामस्थान (वैश्विक नामस्थान) के सदस्यों को संदर्भित करते हैं।

ये दो नाम समान चर को इंगित नहीं करते हैं। घोषणा int x; एक चर परिभाषित करता है। क्योंकि कार्यक्रम में ऐसी दो परिभाषाएं हैं, कार्यक्रम में दो चर हैं। एक अनुवाद इकाई में "x" नाम इन चरों में से एक को दर्शाता है; अन्य अनुवाद इकाई में "x" नाम दूसरे को दर्शाता है। इसलिए, कार्यक्रम खराब गठित है।

+2

आप इस निष्कर्ष तक कैसे पहुंचते हैं कि दो नाम 'x' समान चर को इंगित नहीं करते हैं? – ecatmur

+1

@ecatmur: दो चर हैं क्योंकि दो परिभाषाएं हैं: 'int x;' स्थिर भंडारण अवधि के साथ एक चर परिभाषित करता है। ऐसी दो परिभाषाएं हैं, इसलिए दो चर हैं।यदि कार्यक्रम ल्यूक डैंटन द्वारा सुझाए गए अनुसार संशोधित किया गया था, तो केवल एक चर होगा क्योंकि केवल एक परिभाषा होगी ('बाहरी int x;' 'x' का _definition_ नहीं है; यह केवल _declaration_ है)। –

+0

यदि 'int x 'के बजाय, घोषणाओं ने' कक्षा y {};' या 'नेमस्पेस z {}' (दोनों परिभाषाएं) ली, नाम 'y' और' z' क्रमशः उसी प्रकार या नामस्थान को इंगित करेंगे । चर 'x' कैसे भिन्न है? – ecatmur

0

उस संकलन में कोई त्रुटि नहीं है, त्रुटि इसके संबंध में है। डिफ़ॉल्ट रूप से आपके वैश्विक चर या फ़ंक्शन अन्य फ़ाइलों के लिए सार्वजनिक होते हैं (extern संग्रहण होते हैं) इसलिए अंत में जब लिंकर आपके कोड को लिंक करना चाहता है तो यह x के लिए दो परिभाषाओं को देखता है और यह उनमें से एक का चयन नहीं कर सकता है, इसलिए यदि आप उपयोग नहीं करते हैं other.cpp और उपाध्यक्ष कविता में main.cpp की x उन्हें स्थिर (है कि केवल फ़ाइल है कि यह शामिल करने के लिए दिखाई दे मतलब है)

// other.cpp 
static int x; 

// main.cpp 
static int x; 
1

मानक अप्रयुक्त चर की परिभाषा के बारे में कुछ नहीं कहा तो आप निहित नहीं हो सकता है कि वहाँ हो सकता है बनाने के एकाधिक हो:

अपरिभाषित व्यवहार भी उम्मीद की जा सकती है डी जब यह अंतर्राष्ट्रीय मानक व्यवहार की किसी भी स्पष्ट परिभाषा के वर्णन को छोड़ देता है।

तो यह संकलन कर सकते हैं और अच्छी तरह से चलाने के लिए या त्रुटि संदेश के साथ अनुवाद के दौरान बंद कर सकता है या क्रम आदि

संपादित क्रैश हो सकता है: जेम्स McNellis वास्तव में मानक का जवाब वास्तव में इसके बारे में नियम हैं देखें।

+0

कार्यक्रम अपरिभाषित व्यवहार प्रदर्शित नहीं करता है; यह खराब गठित है। यह एक निदान अर्थपूर्ण शासन का उल्लंघन करता है। –

+0

@ जेम्स हां, यह बीमार गठित है, लेकिन मैंने जो भी कहा है, वह अभी भी रखता है, यदि मानक कुछ का वर्णन करता है तो यह हमेशा परिभाषित नहीं होता है कि क्या होता है, पाठक केवल यादृच्छिक चीज़ को इंगित नहीं कर सकता है। –

5

आप सही हैं कि इस संबंध में मानक गलती है। मुझे एहसास है कि यह मामला 3.2p1 (आपके प्रश्न के अनुसार प्रति अनुवाद इकाई की एक परिभाषा पर) और 3.2p6 के बीच के अंतराल में पड़ता है (जो वर्णन करता है कि वर्ग, अंकन, इनलाइन फ़ंक्शंस और विभिन्न टेम्पलेट्स में डुप्लिकेट परिभाषाएं कैसे हो सकती हैं अनुवाद इकाइयों)।

तुलना के लिए, सी में, 6.9p5 की आवश्यकता है कि (मेरे जोर):

एक बाहरी परिभाषा एक बाहरी घोषणा भी एक समारोह की एक परिभाषा (एक इनलाइन परिभाषा के अलावा) या एक है वस्तु। यदि बाहरी लिंकेज के साथ घोषित एक पहचानकर्ता को अभिव्यक्ति में उपयोग किया जाता है (sizeof या _Alignof ऑपरेटर के ऑपरेशन के हिस्से के अलावा जिसका परिणाम एक पूर्णांक निरंतर है), पूरे कार्यक्रम में कहीं पहचानकर्ता के लिए बिल्कुल एक बाहरी परिभाषा होगी; अन्यथा, से अधिक नहीं होगा।

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

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