क्या छपेगा? ६ ६ या ६ 7? और क्यों?
void foo()
{
static int x = 5;
x++;
printf("%d", x);
}
int main()
{
foo();
foo();
return 0;
}
क्या छपेगा? ६ ६ या ६ 7? और क्यों?
void foo()
{
static int x = 5;
x++;
printf("%d", x);
}
int main()
{
foo();
foo();
return 0;
}
जवाबों:
यहां दो मुद्दे हैं, जीवनकाल और गुंजाइश।
चर का दायरा वह है जहां चर नाम देखा जा सकता है। यहां, x केवल फ़ंक्शन फू () के अंदर दिखाई देता है।
एक चर का जीवनकाल वह अवधि है जिस पर यह मौजूद है। यदि x को कीवर्ड स्थिर के बिना परिभाषित किया गया था, तो जीवनकाल फू () से फू में वापसी () में प्रवेश से होगा; इसलिए इसे हर कॉल पर 5 पर फिर से शुरू किया जाएगा।
कार्यक्रम के जीवनकाल के लिए एक चर के जीवनकाल का विस्तार करने के लिए कीवर्ड स्टैटिक कार्य करता है; उदाहरण के लिए, इनिशियलाइज़ेशन एक बार और केवल एक बार होता है और फिर वैरिएबल इसकी वैल्यू को बरकरार रखता है - जो भी यह आया है - भविष्य के सभी कॉल्स को लुभाने के लिए ()।
आउटपुट : ६ 6
कारण : स्थिर चर को केवल एक बार (ऑटो चर के विपरीत) आरंभ किया जाता है और स्थैतिक चर की आगे की परिभाषा रनटाइम के दौरान बाईपास हो जाएगी। और यदि इसे मैन्युअल रूप से प्रारंभ नहीं किया गया है, तो यह मूल्य 0 से स्वचालित रूप से प्रारंभ होता है। इसलिए,
void foo() {
static int x = 5; // assigns value of 5 only once
x++;
printf("%d", x);
}
int main() {
foo(); // x = 6
foo(); // x = 7
return 0;
}
६ 7
संकलक व्यवस्था करता है कि स्थिर वैरिएबल आरंभीकरण हर बार फ़ंक्शन के दर्ज होने पर नहीं होता है
यह निम्नलिखित कार्यक्रम के रूप में ही है:
static int x = 5;
void foo()
{
x++;
printf("%d", x);
}
int main()
{
foo();
foo();
return 0;
}
उस कार्यक्रम में स्थैतिक कीवर्ड जो कुछ भी करता है वह यह है कि संकलक (अनिवार्य रूप से) 'अरे, मेरे पास यहां एक चर है जिसे मैं किसी और तक नहीं पहुंचना चाहता, किसी और को यह न बताएं कि यह मौजूद है'।
एक विधि के अंदर, स्थैतिक कीवर्ड संकलक को ऊपर के समान बताता है, लेकिन यह भी कि, 'किसी को यह न बताएं कि यह इस फ़ंक्शन के बाहर मौजूद है, यह केवल इस फ़ंक्शन के अंदर ही होना चाहिए'।
आशा है कि ये आपकी मदद करेगा
x
मुख्य के साथ प्रोक और फ्यूज़ कर सकते हैं ; यह वैश्विक है। मूल उदाहरण x
में foo के लिए स्थानीय था, केवल उस ब्लॉक के अंदर दिखाई देता है, जो आमतौर पर बेहतर होता है: यदि foo x
पूर्वानुमान और दृश्यमान तरीकों से बनाए रखने के लिए मौजूद है, तो दूसरों को प्रहार करने देना आमतौर पर खतरनाक है। इसे दायरे में रखने के एक अन्य लाभ के रूप में foo()
यह foo()
पोर्टेबल भी रहता है ।
c
, इसलिए इस संदर्भ में, आपका उदाहरण वैश्विक दायरे में अवैध होगा। (C को ग्लोबल्स के लिए निरंतर इनिशियलाइज़र की आवश्यकता होती है, C ++ नहीं)।
जब तक आपका प्रोग्राम चलता है, तब तक एक फ़ंक्शन के अंदर एक स्थिर चर में एक जीवनकाल होता है। जब आपके फ़ंक्शन को कॉल किया जाता है और जब आपका फ़ंक्शन वापस आ जाता है तो उसे आवंटित नहीं किया जाएगा।
की घोषणा x
अंदर है, foo
लेकिन x=5
इनिशियलाइज़ेशन बाहर से होता है foo
!
यहां हमें समझने की जरूरत है
static int x = 5;
के रूप में ही नहीं है
static int x;
x = 5;
अन्य उत्तरों ने यहाँ महत्वपूर्ण शब्दों, गुंजाइश और जीवनकाल का उपयोग किया है, और बताया कि कार्यक्षेत्र x
में इसकी घोषणा के बिंदु से लेकर कार्य foo
के अंत तक का दायरा है foo
। उदाहरण के लिए मैंने फ़ंक्शन के अंत में घोषणा को स्थानांतरित करके जाँच की, और यह x
अघोषित बनाता हैx++;
कथन में ।
तो static int x
कथन का (स्कोप) हिस्सा वास्तव में लागू होता है जहां आप इसे पढ़ते हैं, कहीं INSIDE फ़ंक्शन को करता है और केवल वहाँ से, फ़ंक्शन के अंदर से ऊपर नहीं।
हालांकि x = 5
(जीवन) के बयान का हिस्सा है चर का प्रारंभ और हो रहा बाहर कार्यक्रम लोड हो रहा है के भाग के रूप समारोह का। चर x
का मान के साथ जन्म होता है5
है जब प्रोग्राम लोड होता है।
मैंने इसे टिप्पणियों में से एक में पढ़ा: " इसके अलावा, यह वास्तव में भ्रमित करने वाले हिस्से को संबोधित नहीं करता है, जो कि इस तथ्य को दर्शाता है कि शुरुआती कॉल बाद के कॉल पर छोड़ दिया गया है। " यह सभी कॉल पर छोड़ दिया जाता है। वैरिएबल का प्रारंभ फ़ंक्शन फ़ंक्शन कोड के बाहर उचित है।
5 का मूल्य सैद्धांतिक रूप से निर्धारित किया जाता है, भले ही फू को बिल्कुल भी बुलाया जाए या नहीं, हालांकि एक कंपाइलर फंक्शन को ऑप्टिमाइज़ कर सकता है यदि आप इसे कहीं भी कॉल नहीं करते हैं। 5 की वैल्यू को चर में पहले कभी भी बुलाया जाना चाहिए।
foo
बयान के अंदरstatic int x = 5;
किसी भी कोड को उत्पन्न करने की संभावना नहीं है।
मुझे पता चलता है कि x
जब मैं foo
किसी कार्यक्रम को अपने कार्यक्रम में डालता हूं , तो पता का उपयोग होता है , और फिर (सही ढंग से) यह अनुमान लगाया कि यदि मैं फिर से कार्यक्रम चलाता हूं तो उसी स्थान का उपयोग किया जाएगा। नीचे दी गई आंशिक स्क्रीन कैप्चर से पता चलता है कि पहली कॉल करने से पहले भी x
इसका मूल्य 5
है foo
।
आउटपुट होगा 6 7
। एक स्थिर चर (किसी फ़ंक्शन के अंदर है या नहीं) का अनुवाद एक बार शुरू किया जाता है, इससे पहले कि अनुवाद इकाई में कोई भी फ़ंक्शन निष्पादित हो। उसके बाद, यह संशोधित होने तक अपने मूल्य को बरकरार रखता है।
Vadiklk,
क्यों ...? कारण यह है कि स्थिर चर को केवल एक बार आरंभीकृत किया जाता है, और पूरे कार्यक्रम में इसके मूल्य को बनाए रखता है। का अर्थ है, आप फ़ंक्शन कॉल के बीच स्थिर चर का उपयोग कर सकते हैं। यह भी कहा जाता है कि "किसी फ़ंक्शन को कितनी बार कहा जाता है" गिनने के लिए इस्तेमाल किया जा सकता है
main()
{
static int var = 5;
printf("%d ",var--);
if(var)
main();
}
और उत्तर 5 4 3 2 1 है न कि 5 5 5 5 5 5 .... (अनंत लूप) जैसा कि आप उम्मीद कर रहे हैं। फिर से, कारण स्थिर वैरिएबल को एक बार आरंभीकृत किया जाता है, जब अगली बार मुख्य () कहा जाता है, तो इसे 5 के लिए इनिशियलाइज़ नहीं किया जाएगा क्योंकि यह प्रोग्राम में पहले से ही इनिशियलाइज़ हो गया है। इसलिए हम वैल्यू बदल सकते हैं लेकिन रीइंस्ट्रिक्ट नहीं कर सकते हैं। स्थैतिक चर कैसे काम करता है।
या आप भंडारण के अनुसार विचार कर सकते हैं: स्थैतिक चर किसी प्रोग्राम के डेटा अनुभाग पर संग्रहीत होते हैं और वे चर जो डेटा अनुभाग में संग्रहीत किए जाते हैं, उन्हें एक बार प्रारंभ किया जाता है। और आरंभीकरण से पहले उन्हें बीएसएस अनुभाग में रखा गया है।
बदले में ऑटो (स्थानीय) वैरिएबल स्टैक पर संग्रहीत किए जाते हैं और स्टैक पर सभी वेरिएबल्स को हर समय पुनर्निर्मित किया जाता है जब फ़ंक्शन को नया FAR कहा जाता है (फ़ंक्शन सक्रियण रिकॉर्ड) इसके लिए बनाया गया है।
अधिक समझ के लिए ठीक है, उपरोक्त उदाहरण "स्टैटिक" के बिना करें और आपको बताएं कि आउटपुट क्या होगा। इससे आपको इन दोनों के बीच के अंतर को समझने में मदद मिलेगी।
धन्यवाद जावेद
आइए अभी स्टैटिक वेरिएबल्स पर विकिपीडिया लेख पढ़ें ...
स्टैटिक लोकल वैरिएबल: एक फंक्शन के अंदर स्टैटिक घोषित किए गए वैरिएबल को ऑटोमैटिक लोकल वैरिएबल के समान स्कोप होते हुए स्टेटिक रूप से आवंटित किया जाता है। इसलिए जो भी फ़ंक्शन एक कॉल के दौरान फ़ंक्शन को अपने स्थिर स्थानीय चर में रखता है वह तब भी मौजूद रहेगा जब फ़ंक्शन को फिर से कॉल किया जाता है।
आपको 6 7 प्रिंट मिलेंगे, जैसा कि आसानी से जांचा जाता है, और यहाँ कारण है: कब foo
पहली बार बुलाया जाता है, तो स्थिर चर x को 5 से शुरू किया जाता है। फिर इसे 6 तक बढ़ाया जाता है और मुद्रित किया जाता है।
अब अगली कॉल के लिए foo
। कार्यक्रम स्थैतिक चर आरंभीकरण को छोड़ देता है, और इसके बजाय मान 6 का उपयोग करता है जो पिछली बार के आसपास x को सौंपा गया था। निष्पादन सामान्य रूप से आगे बढ़ता है, जिससे आपको 7 मूल्य मिलते हैं।
6 और 7 क्योंकि स्थिर चर केवल एक ही बार होता है, इसलिए 5 ++ 1 कॉल पर 6 हो जाता है 6 ++ 2 कॉल पर 7 हो जाता है नोट -2 जब यह होता है तो x का मूल्य 5 के बजाय 6 होता है क्योंकि x स्थिर चर है।
C ++ 11 में कम से कम, जब स्थानीय स्थिर वैरिएबल को इनिशियलाइज़ करने के लिए प्रयोग किया जाने वाला एक्सप्रेशन 'कॉन्स्टेक्सप्र' (कंपाइलर द्वारा मूल्यांकन नहीं किया जा सकता) नहीं है, तो फंक्शन के पहले कॉल के दौरान इनिशियलाइज़ेशन होना चाहिए। सबसे सरल उदाहरण सीधे स्थानीय स्थैतिक चर को पहचानने के लिए एक पैरामीटर का उपयोग करना है। इस प्रकार कंपाइलर को यह पता लगाने के लिए कोड का उत्सर्जन करना होगा कि क्या कॉल पहले एक है या नहीं, जिसके बदले में स्थानीय बूलियन चर की आवश्यकता होती है। मैंने ऐसे उदाहरण संकलित किए हैं और जाँच की है कि यह विधानसभा कोड देखकर सच है। उदाहरण इस प्रकार हो सकता है:
void f( int p )
{
static const int first_p = p ;
cout << "first p == " << p << endl ;
}
void main()
{
f(1); f(2); f(3);
}
बेशक, जब एक्सट्रैस 'कॉन्स्ट्रेक्स' है, तो इसकी आवश्यकता नहीं है और आउटपुट असेंबली कोड में कंपाइलर द्वारा संग्रहीत मूल्य का उपयोग करके प्रोग्राम लोड पर वैरिएबल को इनिशियलाइज़ किया जा सकता है।