2010-07-30 10 views
8

संभव डुप्लिकेट:
Why global and static variables are initialized to their default values?स्थिर वैरिएबल शून्य पर स्वत: प्रारंभ क्यों हैं?

तकनीकी कारण ऐसा होता है क्या है? और क्या यह सभी प्लेटफॉर्म पर मानक द्वारा समर्थित है? क्या यह संभव है कि स्थिर कार्यान्वयन स्पष्ट रूप से प्रारंभ नहीं किए जाने पर कुछ कार्यान्वयन अपरिभाषित चर वापस आ सकते हैं?

+2

फिर से खोलने के लिए वोट दिया गया क्योंकि यह प्रश्न यह भी पूछता है कि कुछ कंपाइलर स्थिर चर को शून्य नहीं करते हैं या नहीं। इसका जवाब है हाँ! कुछ डोमेन-विशिष्ट कंपाइलर सभी मानकों के अनुरूप नहीं हैं। उदाहरण के लिए, टीआईजीसीसी (टीआई -8 9/9 2/वी 200 कैलकुलेटर के लिए एक सी कंपाइलर), एक स्पष्ट वैरिएबल के साथ एक वैश्विक चर (उदाहरण के लिए 'स्थैतिक int high_score = 0;') प्रोग्राम के रनों में संरक्षित किया जाएगा (जब तक कि यह संग्रहीत न हो फ्लैश मेमोरी में), प्रोग्राम सेटिंग्स को बनाए रखने के लिए एक सरल लेकिन आलसी तरीका प्रदान करना। –

उत्तर

31

यह मानक (§6.7.8/10) के लिए आवश्यक है।

कोई तकनीकी कारण यह होता इस तरह से होना करने के लिए नहीं है, लेकिन यह काफी लंबे समय के लिए इस तरह से है कि मानक समिति यह एक आवश्यकता बना दिया गया है।

इस आवश्यकता को छोड़कर स्थिर चर के साथ काम करना कई (अधिकांश?) मामलों में कुछ और मुश्किल हो जाएगा। विशेष रूप से, आपके पास अक्सर एक बार प्रारंभ करने के लिए प्रारंभिक होता है, और एक भरोसेमंद प्रारंभिक स्थिति की आवश्यकता होती है ताकि आप जान सकें कि कोई विशेष चर प्रारंभ किया गया है या नहीं। उदाहरण के लिए:

int foo() { 
    static int *ptr; 

    if (NULL == ptr) 
     // initialize it 
} 

ptr स्टार्टअप पर एक मनमाना मूल्य को रख सकती हैं, तो आप स्पष्ट रूप से इसे पहचान करने के लिए सक्षम होने के लिए शून्य पर कि क्या आप अभी तक या नहीं अपने एक बार प्रारंभ किया था प्रारंभ करने में होगा।

+1

+1। एएनएसआई सी समिति का मूल जनादेश मौजूदा अभ्यास को संहिताबद्ध करना था, जिसकी वजह से इसकी आवश्यकता थी। – paxdiablo

+3

@paxdiablo: निस्संदेह - यह स्पष्ट रूप से के एंड आर 1 (परिशिष्ट ए, §6 में बताया गया है।8): "प्रारंभिक और बाहरी चर जो प्रारंभ नहीं किए जाते हैं उन्हें 0 के रूप में शुरू करने की गारंटी दी जाती है; स्वचालित और पंजीकृत चर जो प्रारंभ नहीं होते हैं उन्हें कचरे के रूप में शुरू करने की गारंटी दी जाती है।" –

0

अधिकतर क्योंकि स्थैतिक चर को लिंकर द्वारा एक ब्लॉक में एक साथ समूहीकृत किया जाता है, इसलिए स्टार्टअप पर पूरे ब्लॉक को 0 को याद रखना वास्तविक है। मुझे विश्वास नहीं है कि सी या सी ++ मानकों द्वारा आवश्यक है।

+1

यह डॉस और अन्य [गैर-] ऑपरेटिंग सिस्टम को छोड़कर 0 को 'memset'' नहीं है। एक आधुनिक प्रणाली पर, यह "शून्य पृष्ठ" के प्रति-प्रति-लेखन संदर्भ है। मानक लिंक के लिए –

0

इस here के बारे में चर्चा नहीं है:

आईएसओ सी (एएनएसआई सी) में सभी की

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

9

हाँ, यह है क्योंकि यह मानक में है; लेकिन वास्तव में, ऐसा इसलिए है क्योंकि यह मुफ़्त है। स्टेटिक वैरिएबल जेनरेट ऑब्जेक्ट कोड में ग्लोबल वैरिएबल की तरह दिखते हैं। उन्हें .bss में आवंटित किया जाता है और आपके सभी स्थिरांक और अन्य ग्लोबल्स के साथ लोड समय पर प्रारंभ किया जाता है। चूंकि वे जहां रहते हैं, स्मृति के अनुभाग को सीधे आपके निष्पादन योग्य से कॉपी किया गया है, इसलिए उन्हें संकलित समय पर ज्ञात मूल्य के लिए प्रारंभ किया गया है। चुना गया मान 0.

+1

ईएलएफ फाइलों में .bss अनुभाग शून्य लंबाई है। यह लोडर है जो अवरुद्ध शून्य ब्लॉक को प्रारंभ करता है। यदि यह मानक द्वारा आवश्यक नहीं था, तो यह केवल ब्लॉक को अनियमित कर सकता था। – doron

+5

प्रक्रिया स्टार्टअप पर एक अनियंत्रित पृष्ठ वैसे भी शून्य होगा, जब तक कि कर्नेल यादृच्छिक जंक लिखने के तरीके से बाहर न हो जाए। किसी भी आधुनिक कार्यान्वयन पर, बीएसएस एक "गाय पृष्ठ" का एक गाय (प्रतिलिपि-लिखना) संदर्भ है जो सभी प्रक्रियाओं के बीच साझा किया जाता है। यहां तक ​​कि अगर यह नहीं था, तो कर्नेल को अभी भी नई प्रक्रियाओं को यादृच्छिक भौतिक स्मृति की सामग्री को देखने से रोकने के लिए कुछ करना होगा (जिसमें निजी आंतरिक कर्नेल डेटा या अन्य उपयोगकर्ताओं से डेटा हो सकता है) ताकि वे इसे एक साथ सेट कर सकें उपयोगी मूल्य 0 जैसे इसे साफ़ करते समय ... –

0

मान लीजिए कि आप एक सी कंपाइलर लिख रहे थे। आप उम्मीद करते हैं कि कुछ स्थैतिक चर के प्रारंभिक मान होने जा रहे हैं, इसलिए उन मानों को निष्पादन योग्य फ़ाइल में कहीं भी दिखाई देना चाहिए जो आपका कंपाइलर बनाने जा रहा है। अब जब आउटपुट प्रोग्राम चलाया जाता है, तो संपूर्ण निष्पादन योग्य फ़ाइल को स्मृति में लोड किया जाता है। कार्यक्रम की शुरुआत का हिस्सा स्थैतिक चर बनाना है, इसलिए उन सभी प्रारंभिक मानों को उनके अंतिम स्थैतिक चर गंतव्यों में कॉपी किया जाना चाहिए।

या वे करते हैं? एक बार कार्यक्रम शुरू होने के बाद, चर के प्रारंभिक मानों की अब आवश्यकता नहीं है। चर स्वयं निष्पादन योग्य कोड के भीतर स्थित नहीं हो सकता है? फिर मूल्यों की प्रतिलिपि बनाने की कोई आवश्यकता नहीं है।स्थैतिक चर मूल ब्लॉक में मौजूद ब्लॉक के भीतर रह सकते हैं, और उनके लिए कोई प्रारंभिकता नहीं की जानी चाहिए।

यदि ऐसा है, तो आप अनियमित स्थिर चर के लिए एक विशेष मामला क्यों बनाना चाहते हैं? अनियमित स्थिर चर का प्रतिनिधित्व करने के लिए निष्पादन योग्य फ़ाइल में शून्य का एक गुच्छा क्यों न रखें? यह थोड़ी देर के लिए कुछ जगह और बहुत कम जटिलता का व्यापार करेगा।

मुझे नहीं पता कि कोई सी संकलक वास्तव में इस तरह से व्यवहार करता है, लेकिन मुझे संदेह है कि इस तरह से चीजों को करने का विकल्प भाषा के डिजाइन को प्रेरित कर सकता है।

+0

कुछ पुराने सी कंपाइलर्स ने कोड छवि के भीतर प्रारंभिक चर डाल दिया होगा और उन्हें वहां से एक्सेस किया होगा। मुझे पता है कि टर्बो पास्कल ने ऐसा किया था। मुझे वहां अनियमित चर डालने का कोई कारण नहीं दिखता है। शून्य के साथ स्मृति का एक ब्लॉक भरना मुश्किल नहीं है। – supercat

+0

@supercat - शून्य के साथ स्मृति का एक ब्लॉक भरना मुश्किल नहीं है। लेकिन प्रारंभिक और अनियमित श्रेणियों में स्थैतिक चर को अलग करना और उनके लिए अलग-अलग मेमोरी ब्लॉक आवंटित करना-जबकि कठिन नहीं है-अनावश्यक है। –

+0

डिस्क और स्मृति दोनों में, अंतरिक्ष को बचाने के लिए यह "आवश्यक" है। यदि आप इसे "अनावश्यक" कहते हैं तो आपको कोडिंग रोकना चाहिए ... –

1

बेशक कोई बहस नहीं है कि यह सी मानकों में है। तो एक अनुपालन संकलक इस तरह से व्यवहार करने की उम्मीद है।

यह क्यों किया गया था इसके पीछे तकनीकी कारण सी स्टार्टअप कोड कैसे काम करता है इस पर रूट किया जा सकता है। आमतौर पर कई मेमोरी सेगमेंट होते हैं जिन्हें लिंकर को कोड (टेक्स्ट) सेगमेंट, ब्लॉक स्टोरेज सेगमेंट और प्रारंभिक वैरिएबल सेगमेंट सहित कंपाइलर आउटपुट डालना पड़ता है।

गैर स्थैतिक फ़ंक्शन चर के पास भौतिक संग्रहण नहीं है जब तक कि फ़ंक्शन का दायरा रनटाइम पर नहीं बनाया जाता है, इसलिए लिंकर उनसे कुछ भी नहीं करता है।

पाठ्यक्रम कोड (या पाठ) सेगमेंट में पाठ्यक्रम कोड चला जाता है लेकिन मान वैश्विक और स्थैतिक चर प्रारंभ करने के लिए उपयोग किया जाता है। प्रारंभिक चर स्वयं (यानी उनके पते) आरंभिक मेमोरी सेगमेंट में जाते हैं। अनियंत्रित वैश्विक और स्थैतिक चर ब्लॉक स्टोरेज (बीएसएस) सेगमेंट में जाते हैं।

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

सीआरटी (सी रनटाइम) भी बीएसएस को शून्य करता है जिसमें सभी वैश्विक और स्थिर चर शामिल हैं जिनके प्रारंभिक नहीं हैं। यह संभवतः अनियमित डेटा के खिलाफ सावधानी के रूप में किया गया था। यह एक अपेक्षाकृत सीधा ब्लॉक भरने का ऑपरेशन है क्योंकि सभी वैश्विक और स्थैतिक चर एक पते खंड में एक साथ फंस गए हैं।

पाठ्यक्रम तैरता के

और डबल्स मई विशेष हैंडलिंग की आवश्यकता होती है, क्योंकि उनके 0.0 मूल्य सब शून्य बिट्स नहीं किया जा सकता है, तो चल प्रारूप आईईईई नहीं है 754

ध्यान दें कि जब से autovariables कार्यक्रम लोड करते समय मौजूद नहीं है वे रनटाइम स्टार्टअप कोड द्वारा प्रारंभ नहीं किए जा सकते हैं।

+0

आईईईई 754 फ्लोटिंग पॉइंट मानक विशेष रूप से डिज़ाइन किया गया है ताकि +0 सभी शून्य बिट्स हो। क्या आपने सी के कार्यान्वयन को देखा है जो फ़्लोटिंग पॉइंट मानों का एक और प्रतिनिधित्व करता है जिसके लिए यह सच नहीं है? –

+0

@ जेफरी: मैंने टीआई जैसे विशिष्ट फ्लैट प्रारूपों के लिए कंपाइलर्स का उपयोग किया है। लेकिन अब मैं 100% निश्चित नहीं हूं अगर उनके पास वह संपत्ति भी थी। –

+2

@ जेफरी: नहीं, टीआई प्रारूप सभी शून्य बिट्स के रूप में 0.0 को एन्कोड नहीं करता है। यह 0.0 की विशिष्ट पहचान करने के लिए -128 के एक्सपोनेंट की आवश्यकता है। –

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