2013-08-09 4 views
6

मुझे समझ में नहीं आता कि यह क्यों काम नहीं करता है।अनुवाद इकाई में `स्थिर 'परिभाषा और' बाहरी घोषणा 'का आदेश

extern int i; 

int main() 
{ 
    printf(" %d ", i); 
} 

static int i =3; 

इसके अलावा, इस काम नहीं करता है:

extern int i; 

static int i =3; 

int main() 
{ 
    printf(" %d ", i); 
} 

लेकिन अगर static चर extern declaration से पहले परिभाषित किया गया है यह काम करता है:

static int i =3; 

extern int i; 

int main() 
{ 
    printf(" %d ", i); 
} 

मैं extern int i से समझने के रूप में बताता है i है कि वर्तमान कहीं और और यहां यह कैसा दिखता है (int i)

लेकिन, कहीं और साधन:

1) हो सकता है, एक global variable रूप same अनुवाद इकाई में बाद में बात।

2) शायद, other अनुवाद इकाई में।

मैं सोच रहा था कि (1) मान्य होगा, भले ही static int i = 3 ने वर्तमान अनुवाद इकाई को i के दायरे को प्रतिबंधित कर दिया है, जहां इसे परिभाषित किया गया है।

static int i =3global (मेरा मतलब है कि यह अनुवाद इकाई में कम से कम दिखाई देता है) यहां तक ​​कि इसके अनुवाद इकाई के लिए सीमित दायरा है? तो संकलक इसे खोजने में असमर्थ क्यों नहीं है?

जब मैं पहली बार दो संस्करणों मैं निम्नलिखित संकलन समय त्रुटि मिलती संकलन:

error: static declaration of ‘i’ follows non-static declaration 
note: previous declaration of ‘i’ was here 

मैं यह त्रुटि संदेश को समझने में असमर्थ हूँ। साथ ही, यह एक स्थिर declaration के रूप में क्यों शिकायत कर रहा है यह definition भी नहीं है?

+0

वास्तव में "काम नहीं करता" क्या है? क्या यह एक संकलन मुद्दा है? रनटाइम मुद्दा? मैं वीएस 2010 के साथ अपना कोड संकलित कर रहा हूं और ऐसा लगता है कि यह ठीक से काम कर रहा है। – Nbr44

+0

जीसीसी कॉमप्लर, मुझे एक संकलन समय त्रुटि स्थिर स्थिरता मिलती है, मैं गैर स्थैतिक घोषणा का पालन करता हूं। –

उत्तर

6

C11 6.2.2 सम्पर्क धारा 4

For an identifier declared with the storage-class specifier extern in a scope in which a prior declaration of that identifier is visible,31) if the prior declaration specifies internal or external linkage, the linkage of the identifier at the later declaration is the same as the linkage specified at the prior declaration. If no prior declaration is visible, or if the prior declaration specifies no linkage, then the identifier has external linkage.

तो दूसरी घोषणा पहले वापस अपने उदाहरण के लिए का पालन करेंगे, 1 और 2 उदाहरण i एक extern भंडारण स्तरीय होगा। संकलक सोचता है कि यह एक त्रुटि है।

तीसरे उदाहरण में, istatic होगा क्योंकि static पहले दिखाता है। यह कोई समस्या नहीं होनी चाहिए।

और, सी 11 6.2 की धारा 7 में।पहचानकर्ता

If, within a translation unit, the same identifier appears with both internal and external linkage, the behavior is undefined.

तो यह दोनों static और एक ही अनुवाद इकाई में extern के साथ एक ही चर घोषित करने के लिए नहीं बेहतर है की 2 सम्पर्क।

+0

हां, मैं सहमत हूं। लेकिन फिर भी मुझे चिंता है कि '3'rd संस्करण हमेशा क्यों काम करता है? कई कंपाइलर्स भर में। –

+0

@UchiaItachi: आप तीसरे संस्करण के बारे में चिंतित क्यों हैं? यह उत्तर सी मानक से पाठ उद्धृत करता है जो इसे समझाता है: जब 'बाहरी' घोषणा आंतरिक ('स्थिर ') या बाहरी संबंध के साथ घोषणा का पालन करती है, तो पूर्व घोषणा का उपयोग किया जाता है। –

+0

@UchiaItachi एक बात के लिए, भले ही आपने उन सभी कंपाइलरों का परीक्षण किया जो स्पष्ट रूप से आप नहीं कर सकते हैं, और यह सब काम करता है, इसका मतलब यह नहीं है कि यह परिभाषित व्यवहार है। मानक फैसला करने वाला एक है। –

2

खैर, एक चर या तो extern या static है। याद रखें कि वैश्विक स्तर पर static इसकी दृश्यता केवल वर्तमान अनुवाद इकाई तक सीमित करता है, जबकि extern यह बताता है कि यह विभिन्न अनुवाद इकाइयों में दिखाई देता है।

+0

मुझे पता है कि 'स्थैतिक' दृश्यता को पुनः प्राप्त करता है और 'बाहरी' वर्तमान अनुवाद सहित अन्य अनुवाद इकाइयों में डुबो सकता है। लेकिन कोड काम करता है अगर मैं पहले स्थिर चर को परिभाषित करता हूं और एक बाहरी घोषणा देता हूं कि यह 'स्थिर 'और' बाहरी 'है। –

+0

वास्तव में यह वास्तव में मुझे स्टंप कर चुका है, लेकिन मेरा एकमात्र स्पष्टीकरण त्रुटि संदेश ही है: 'i' की स्थिर घोषणा गैर स्थैतिक घोषणा का पालन करती है। जैसा कि मैं समझता हूं कि 'स्थैतिक' किसी गैर-स्थैतिक घोषणा से पहले होना चाहिए। और उस समय तक 'बाहरी' तक पहुंच गया है, वहां पहले से ही 'i' की परिभाषा है कि' बाहरी 'खुश है। – Nobilis

0

static और फिर extern के रूप में कुछ घोषित करने का कोई मतलब नहीं है। ऐसा करना अपरिभाषित व्यवहार है, इसलिए ऐसा मत करो। पहचानकर्ता के

+0

लेकिन क्यों नहीं 'बाहरी' घोषणा के लिए है? यह बताने के लिए कि फ़ाइल को आगे परिभाषित किया गया है? और मुझे पता है कि आपका कोड काम करता है जैसा कि मैंने पहले ही अपने प्रश्न में उल्लेख किया है। –

+0

@UchiaItachi, मेरा जवाब संपादित किया, यह अभी सही है। यह अपरिभाषित व्यवहार है। –

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