2010-08-21 19 views
6

मेरे पास निम्न चर से जुड़ाव के बारे में कुछ प्रश्न हैं।विभिन्न कॉन्स/स्थिर चर के लिंक

  1. पहले static, तो extern

    static int a; // (a) 
    extern int a; // (b) valid, 'a' still internal 
    
    : सी ++ 03 के 7.1.1/7 के उदाहरण के द्वारा और compilers (Comeau, बजना और जीसीसी) के साथ प्रयोग कर, मैं निम्नलिखित लिंकेज प्रकार के लिए आया था

    यह धारा 3.5 के अनुसार मुझे स्पष्ट है: (ए) आंतरिक संबंध का तात्पर्य है। और (बी) आंतरिक संबंध का भी तात्पर्य है, क्योंकि "ए" नाम स्थिर घोषित किया गया है (द्वारा (ए))।

  2. पहले extern, तो static

    extern int b; // (c) 
    static int b; // (d) invalid! 
    

    सबसे पहले, (ग) बाहरी लिंकेज निकलता है। लेकिन (डी) आंतरिक संबंध का तात्पर्य है क्योंकि नाम "बी" को स्थिर (डी) द्वारा घोषित किया गया है। यह 7.1.1/7 के अनुसार अमान्य है, क्योंकि जुड़ाव जुड़ाव संगत नहीं है।

  3. पहले const, तो extern

    const double pi1 = 3.14; // (e) 
    extern const double pi1; // (f) valid and 'pi1' is internal 
    

    सबसे पहले, (ई), आंतरिक संबंध का अर्थ है, क्योंकि यह स्थिरांक है, और न तो स्पष्ट निर्वासन और न ही पहले से गर्भित बाहरी लिंकेज की घोषणा की। और (एफ) बाहरी संबंध को इंगित करना चाहिए और एक त्रुटि होनी चाहिए, क्योंकि यह स्पष्ट रूप से नाम बाहरी घोषित करता है, लेकिन कंपाइलर्स इसे आंतरिक रखते हैं! ऐसा क्यों?यह मेरा सवाल है।

  4. पहले extern, तो const

    extern const double pi2; // (g) 
    const double pi2 = 3.14; // (h) valid and 'pi2' is external 
    

    अब, (छ) बाहरी लिंकेज क्योंकि हम स्पष्ट रूप से निर्वासन घोषित निकलता है। और (एच) बाहरी संबंध का भी अर्थ है क्योंकि (जी) स्पष्ट रूप से घोषित बाहरी।:


मैं प्रयोगात्मक बाहर लिंकेज 3 और 4 के लिए निम्नलिखित टेम्पलेट (दूसरा तर्क बाहरी लिंकेज के लिए आवश्यक है)

template<typename T, T&> struct ensure { }; 

ensure<const double, pi1> e1; // failed 
ensure<const double, pi2> e2; // succeeded 

सारांश के साथ मिल गया है Charles Bailey साथ चर्चा निकला काफी उपयोगी होने के लिए और पता चला 3.5/3, जहां importa के दो संभव व्याख्याओं देखते हैं एनटी बुलेट प्वाइंट

नाम का नाम स्कोप (3.3।5) आंतरिक लिंकेज अगर यह

  • एक वस्तु या संदर्भ है कि स्पष्ट रूप से स्थिरांक की घोषणा की और न स्पष्ट रूप से घोषित निर्वासन और न ही पहले से बाहरी लिंकेज के लिए घोषित किया जाता है का नाम है है;

अगर हम बात (f) को देखो, तो दो व्याख्याओं अलग निष्कर्ष करने के लिए आते हैं, के रूप में नीचे

  1. दिखाया पहली व्याख्या लिखते हैं कि pi1const घोषित किया जाता है, लेकिन यह भी extern घोषित किया जाता है। परिवर्तनीय इस प्रकार बाहरी लिंकेज है।

  2. दूसरी व्याख्या एक ही घोषणा के संदर्भ में "घोषित" के दोनों अवसरों की व्याख्या करती है। इस तरह, इसका मतलब है कि यह const घोषित किया गया है, लेकिन extern const नहीं है। हम ध्यान देते हैं कि (e) को const और extern const घोषित नहीं किया गया है, इस प्रकार हम pi1 आंतरिक लिंकेज देते हैं।

अब कौन सी व्याख्या सही है? मैं उस शब्द से निर्धारित नहीं कर सकता, लेकिन संकलक इस दूसरे तरीके की व्याख्या करते हैं। विशेष रूप से, यदि हम पहली व्याख्या लेते हैं, तो 3.5/3 का अंतिम उद्धृत हिस्सा अनिवार्य होगा, क्योंकि कोई मान्य परिदृश्य नहीं होगा जिसमें नाम const घोषित किया जाएगा और पहले बाहरी लिंक के साथ घोषित किया गया था लेकिन स्पष्ट extern के बिना।

+1

शायद मुझे कुछ याद आ रहा है, लेकिन 3 1 जैसा नहीं है? (यानी, 'pi1' नाम' स्थिर घोषित 'है?)। हालांकि मुझे लगता है कि मैंने सिर्फ सवाल पूछेगा कि क्यों 4 अमान्य नहीं है। – GManNickG

+0

@GMan, इन दो मामलों के लिए 3.5/3 देखें। वे विभिन्न बुलेट बिंदुओं से संभाले जाते हैं। –

+0

@GMan 4 के लिए, पहले इसे बाहरी बना दिया गया और दूसरा इसे आंतरिक नहीं बनाता है, क्योंकि नाम स्पष्ट रूप से बाहरी घोषित किया गया था (पहली घोषणा द्वारा)। तो दोनों केवल पहले, साथ ही पहले और दूसरे दोनों एक ही लिंक को दर्शाते हैं। 2 के लिए, केवल पहले बाहरी संबंध का तात्पर्य है, लेकिन पहले और दूसरे एक साथ आंतरिक संबंध को इंगित करते हैं क्योंकि नाम स्पष्ट रूप से दूसरे द्वारा स्थिर घोषित किया जाता है। इस प्रकार यह अमान्य है। –

उत्तर

4
const double pi1 = 3.14; // (e) 
extern const double pi1; // (f) valid and 'pi1' is internal 

मेरी व्याख्या निम्नानुसार है। किसी नाम के संबंध पर विचार करते समय हम पिछली घोषणाओं के साथ-साथ पार्स में इस बिंदु पर व्याख्या किए जाने पर विचार करते हैं। यही कारण है कि static int a; extern int a; ठीक है, लेकिन extern int b; static int b; नहीं है।

पहले घोषणा का सामना पर हम ध्यान दें कि pi1 स्पष्ट const घोषित किया जाता है लेकिन न तो स्पष्ट रूप से extern घोषित है और न ही पहले से बाहरी लिंकेज के लिए की घोषणा की। यह 3.5/2 विकल्पों में से एक से मेल खाता है इसलिए pi1 में आंतरिक संबंध है।

दूसरी घोषणा हम चाहते हैं का सामना पर pi1 एक वस्तु है कि स्पष्ट रूप से const घोषित किया जाता है लेकिन न तो स्पष्ट रूप से घोषित का नाम है और न ही extern [... blah ...]। मेरा तर्क है कि ऐसा इसलिए है क्योंकि यह बिंदु (ई) पर घोषित किया गया था।निश्चित रूप से, यह हर जगह इस तरह से घोषित नहीं किया गया है, वैसे ही astatic घोषित ऑब्जेक्ट का नाम था जब हम extern int a; घोषणा पर विचार कर रहे थे, भले ही इसे static घोषित नहीं किया गया था। यह मेरे लिए, इसका मतलब है कि घोषणा (एफ) घोषणा (ई) से एक अलग जुड़ाव नहीं दर्शाती है।

+0

मुझे लगता है कि आपकी व्याख्या समझ में आता है। मुझे लगता है कि मानक क्या कहता है कि यह स्पष्ट रूप से घोषित घोषित किया गया है, लेकिन "बाहरी कॉन्स" नहीं है। क्योंकि अन्यथा बाद के पाठ "न ही पहले बाहरी संबंध होने की घोषणा की;" अनिवार्य होगा: घोषणा "कॉन्स्ट" का उपयोग करती है लेकिन कोई "बाहरी" परिभाषा नहीं होगी, लेकिन अच्छी तरह से गठित होने के लिए, किसी भी अन्य घोषणा के बाद * बाहरी 'का उपयोग करने के लिए * होगा। केवल "बाहरी कॉन्स" व्याख्या में, जो आप लागू करते हैं, मुझे लगता है, अतिरिक्त पाठ अधूरा नहीं है। –

+0

मैंने अपने निष्कर्षों को सारांशित करने के लिए अपना प्रश्न बदल दिया है, और मैं इसे स्वीकार करने जा रहा हूं। –

0

मुझे लगता है कि # 3 में आपने अपने विश्लेषण में एक त्रुटि की है। जहां तक ​​मुझे पता है, const लिंकेज के बारे में कुछ भी नहीं दर्शाता है। मुझे यकीन नहीं है कि आप इस निष्कर्ष पर कैसे आ रहे हैं कि संकलक लिंक को आंतरिक बनाता है। अधिकांश कंपाइलर्स (ऑप्टिमाइज़ेशन के रूप में) कॉन्स्ट वैरिएबल के सभी संदर्भों को उस मान से प्रतिस्थापित कर देंगे, जिस पर इसे प्रारंभ किया गया है, इसलिए कोड कोड में बिल्कुल दिखाई नहीं दे सकता है।

और यदि आपने नहीं किया है, तो यह # 1 से स्पष्ट है कि अगर आंतरिक संबंध के साथ कुछ extern कीवर्ड के साथ घोषित किया गया है जो यह आंतरिक संबंध के साथ रहता है। इसलिए मुझे नहीं पता कि आप एक त्रुटि की अपेक्षा क्यों करेंगे।

और यदि const अंतर्निहित आंतरिक संबंध है, तो # 4 उसी कारण के लिए एक त्रुटि होनी चाहिए # 2 है।

+2

'const' लिंक कैसे मिला है, आंतरिक संबंध को इंगित करता है। 7.1.1/6: "_storage-class-specifier_ के बिना नामस्थान स्कोप में घोषित एक नाम बाहरी लिंकेज है जब तक कि पिछले घोषणापत्र के कारण आंतरिक संबंध नहीं होता है और बशर्ते इसे 'कॉन्स्ट' घोषित नहीं किया जाता है। ऑब्जेक्ट्स ने' const' घोषित किया है और स्पष्ट रूप से घोषित नहीं किया गया 'बाहरी' में आंतरिक संबंध है। " –

0

एक ही नामस्थान क्षेत्र में दोनों (ई) और (एफ) होने के कारण §7.1.1/7 द्वारा "किसी दिए गए इकाई के लिए लगातार घोषणाओं द्वारा निहित लिंक सहमत होंगे।"

इस नियम को निदान की आवश्यकता है।

हालांकि, कम से कम Comau ऑनलाइन उल्लंघन का निदान नहीं करता है।

चीयर्स & hth,

संपादित:। उन्होंने कहा कि वह, मैं DR 426 के रूप में एक और उत्तर यहाँ में उल्लेख देखा, है, और यह जो लोग प्रस्तावित संकल्प का मसौदा तैयार किया लगता है, यह निदान के बजाय यूबी बनाने थे, §7.1.1/7 के बारे में पता नहीं है। मैं इस मुद्दे पर टिप्पणी करने या इसे comp.std.C++ में भी बढ़ाने के लिए नहीं जा रहा हूं क्योंकि मुझे मानकीकरण कार्य मेरे लिए बहुत राजनीतिक और बकवास (मम्बो-जंबो तर्क) माना जाता है। लेकिन किसी भी तरह से, कोड मान्य नहीं है।

+0

"मुम्बो जंबो तर्क" से आपका क्या मतलब है? –

+0

@ जोहान्स: उदा। तर्क यह है कि स्थिरता के लिए एक-कुछ भी अनंत लूप यूबी होना चाहिए। या ओप को स्थानांतरित करने वाले तर्क को फेंकने की अनुमति दी जानी चाहिए (मुझे याद नहीं है कि वह तर्क क्या था)। शीघ्र। चीयर्स, –

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