तीसरे x को इसमें क्या संदर्भित करना चाहिए:

#include <stdio.h>

static char x = '1';

int main(void)
{
    char x = '2';
    {
        extern char x;
        printf("%c\n", x);
    }
}

यह इस उत्तर में उत्पन्न हुआ, और:

सी 2018 6.2.2 4 कहते हैं:

स्टोरेज-क्लास स्पेसिफायर के साथ घोषित एक पहचानकर्ता के लिए बाहरी उस दायरे में जिसमें उस पहचानकर्ता की पूर्व घोषणा दिखाई दे रही है, यदि पूर्व घोषणा आंतरिक या बाहरी लिंकेज को निर्दिष्ट करती है, तो बाद में पहचानकर्ता का लिंकेज घोषणा पूर्व घोषणा में निर्दिष्ट लिंकेज के समान है। यदि कोई पूर्व घोषणा दिखाई नहीं दे रही है, या यदि पूर्व घोषणा कोई लिंकेज निर्दिष्ट नहीं करती है, तो पहचानकर्ता के पास बाहरी संबंध है।

चूंकि x की दो पूर्व घोषणाएं हैं, निम्नलिखित में से प्रत्येक "अगर" खंड सत्य है, पहली पूर्व घोषणा के लिए पहली और दूसरी पूर्व घोषणा के लिए दूसरी:

  • ... यदि पूर्व घोषणा आंतरिक या बाहरी लिंकेज को निर्दिष्ट करती है, तो बाद की घोषणा में पहचानकर्ता का लिंकेज पूर्व घोषणा में निर्दिष्ट लिंकेज के समान है।
  • ... यदि पूर्व घोषणा में कोई संबंध नहीं है, तो पहचानकर्ता का बाहरी संबंध है।

यहां क्लैंग का व्यवहार पहले खंड के उपयोग के अनुरूप है, ताकि तीसरे x में आंतरिक संबंध हो और पहले x के समान वस्तु को संदर्भित करता हो। यहां GCC का व्यवहार दूसरे खंड के उपयोग के अनुरूप है, ताकि तीसरे x का बाहरी संबंध हो और पहले x के साथ विरोध हो, जिसमें आंतरिक संबंध है।

क्या सी मानक हमें यह हल करने का एक तरीका देता है कि इनमें से कौन सा मामला होना चाहिए?

10
Eric Postpischil 18 अक्टूबर 2018, 17:35

1 उत्तर

सबसे बढ़िया उत्तर

तीसरी घोषणा, extern char x, को C 2018 6.2.2 4 के आधार पर बाहरी लिंकेज के साथ x घोषित करना चाहिए, जो कहता है:

स्टोरेज-क्लास स्पेसिफायर के साथ घोषित एक पहचानकर्ता के लिए बाहरी उस दायरे में जिसमें उस पहचानकर्ता की पूर्व घोषणा दिखाई दे रही है, यदि पूर्व घोषणा आंतरिक या बाहरी लिंकेज को निर्दिष्ट करती है, तो बाद में पहचानकर्ता का लिंकेज घोषणा पूर्व घोषणा में निर्दिष्ट लिंकेज के समान है। यदि कोई पूर्व घोषणा दिखाई नहीं दे रही है, या यदि पूर्व घोषणा कोई लिंकेज निर्दिष्ट नहीं करती है, तो पहचानकर्ता के पास बाहरी संबंध है।

घोषणा पर extern char x, x की पहली घोषणा दिखाई नहीं दे रही है, क्योंकि इसे दूसरी घोषणा द्वारा छुपाया गया है। इसलिए, यह "उस पहचानकर्ता की पूर्व घोषणा दृश्यमान है" के लिए योग्य नहीं है। x की दूसरी घोषणा दिखाई दे रही है, इसलिए यह उपरोक्त पैराग्राफ के प्रयोजनों के लिए "पूर्व घोषणा" है।

फिर अंतिम वाक्य को नियंत्रित करना चाहिए: पूर्व घोषणा कोई लिंकेज निर्दिष्ट नहीं करती है (6.2.2 6, बिना extern के ब्लॉक-स्कोप आइडेंटिफ़ायर का कोई लिंकेज नहीं है), इसलिए तीसरे एक्स में बाहरी लिंकेज है।

फिर 6.2.2 7 का उल्लंघन किया जाता है क्योंकि पहले x में आंतरिक संबंध हैं और तीसरे x में बाहरी संबंध हैं:

यदि, किसी अनुवाद इकाई के भीतर, आंतरिक और बाहरी दोनों लिंकेज के साथ एक ही पहचानकर्ता प्रकट होता है, तो व्यवहार अपरिभाषित होता है।

चूंकि किसी भी सिंटैक्स नियम या बाधा का उल्लंघन नहीं किया गया है, इसलिए नैदानिक ​​​​रिपोर्ट करने के लिए मानक द्वारा सी कार्यान्वयन की आवश्यकता नहीं है। चूंकि व्यवहार अपरिभाषित है, यह इस कोड को स्वीकार करने सहित कुछ भी कर सकता है और तीसरे x को उसी ऑब्जेक्ट को पहले x के रूप में संदर्भित कर सकता है। इसलिए, इस संबंध में न तो क्लैंग और न ही जीसीसी के व्यवहार मानक का उल्लंघन करते हैं। हालांकि, चूंकि 6.2.2 7 का उल्लंघन किया गया है, इसलिए निदान को प्राथमिकता दी जा सकती है, और इसकी अनुपस्थिति को क्लैंग का दोष माना जा सकता है।

(पॉल ओगिल्वी और टीसी इस पर मेरी सोच को उनकी टिप्पणियों के साथ सूचित करने के लिए।)

3
Eric Postpischil 18 अक्टूबर 2018, 22:01