लूप के बाहर एक चर घोषित करने और लूप के अंदर स्थिर घोषित करने के बीच अंतर क्या है?


9

ये दो तरीके हैं जो मैं लूप (या किसी फ़ंक्शन) के बाहर एक चर पकड़ सकता हूं।

पहले, मैं इसे लूप के बाहर वैश्विक दायरे के साथ घोषित कर सकता हूं:

void setup()
{
    Serial.begin(9600);
}

int count = 0;

void loop()
{
    Serial.println(count);
    count++;

    delay(250);
}

मैं इसे लूप के अंदर स्थिर भी घोषित कर सकता हूं:

void setup()
{
    Serial.begin(9600);
}

void loop()
{
    static int count = 0;

    Serial.println(count);
    count++;

    delay(250);
}

क्या फर्क पड़ता है, यदि कोई हो, तो इससे क्या होगा?

जवाबों:


10

सबसे बुनियादी अंतर स्कोप का है।

पहले मामले में, आप एक वैश्विक चर घोषित कर रहे हैं। यह एक ऐसा चर है जो अपनी परिभाषा के बाद हर क्षेत्र में सुलभ है।

void setup()
{
    Serial.begin(9600);
}

void inc();
int count = 0;

void loop()
{
    Serial.println(count);
    count++;

    inc();

    delay(500);
}

void inc() //Can edit the value of count
{
  count=count+1;
};

दूसरे मामले में, आप स्थानीय क्षेत्र के साथ एक स्थिर चर घोषित कर रहे हैं। वैरिएबल पूरे प्रोग्राम के लिए ग्लोबल वैरिएबल की तरह ही चलता रहेगा, लेकिन इसे घोषित किए गए कोड ब्लॉक में ही एक्सेस किया जा सकेगा। यह एक ही उदाहरण है, जिसमें केवल एक बदलाव है। countअब अंदर एक स्थिर चर के रूप में घोषित किया गया है loop

void inc();

void loop()
{
    static int count = 0;
    Serial.println(count);
    count++;

    inc();

    delay(500);
}

यह संकलित नहीं करेगा क्योंकि फ़ंक्शन inc()तक पहुंच नहीं है count

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

void setup()
{
    Serial.begin(9600);
}
void another_function();
int state=0;

void loop()
{
    //Keep toggling the state
    Serial.println(state);
    delay(250);
    state=state?0:1;

    //Some unrelated function call
    another_function();
}

void another_function()
{
  //Inadvertently changes state
  state=1;

}

ऐसे मामलों को डीबग करना बहुत कठिन है। हालाँकि, इस प्रकार की समस्या का आसानी से पता लगाया जा सकता है, बस एक स्थिर चर का उपयोग करके।

void setup()
{
    Serial.begin(9600);
}
void another_function();

void loop()
{
    static int state=0;

    //Keep toggling the state
    Serial.println(state);
    delay(250);
    state=state?0:1;

    //Some unrelated function call
    another_function();
}

void another_function()
{
  //Results in a compile time error. Saves time.
  state=1;

}

5

एक कार्यात्मक दृष्टिकोण से, दोनों संस्करण एक ही परिणाम उत्पन्न करते हैं, क्योंकि दोनों मामलों countमें loop()(या क्योंकि यह एक वैश्विक चर है या इसलिए क्योंकि यह चिह्नित है staticऔर इसलिए इसका मूल्य रहता है) के निष्पादन के बीच संग्रहीत किया जाता है ।

तो निर्णय जो निम्नलिखित तर्क के लिए नीचे चुनें:

  1. आम तौर पर, कंप्यूटर विज्ञान में, गुंजाइश के संदर्भ में अपने चर को यथासंभव स्थानीय रखने के लिए प्रोत्साहित किया जाता है । यह आमतौर पर कम साइड-इफेक्ट के साथ बहुत स्पष्ट कोड में परिणाम देता है और किसी अन्य की संभावना को कम करता है जो आपके तर्क को खराब करने वाले वैश्विक चर का उपयोग करता है)। उदाहरण के लिए आपके पहले उदाहरण में, अन्य तर्क क्षेत्र countमान बदल सकते हैं , जबकि दूसरे में, केवल वह विशेष कार्य loop()ऐसा कर सकता है)।
  2. वैश्विक और स्थिर चर हमेशा स्मृति पर कब्जा करते हैं , जहां स्थानीय लोग केवल तब करते हैं जब वे दायरे में होते हैं। आपके उपरोक्त उदाहरणों में कोई फर्क नहीं पड़ता है (क्योंकि एक में आप एक वैश्विक का उपयोग करते हैं, दूसरे में स्थिर चर), लेकिन बड़े और अधिक जटिल कार्यक्रमों में यह हो सकता है और आप गैर-स्थिर स्थानीय लोगों का उपयोग करके मेमोरी को बचा सकते हैं। हालाँकि : यदि आपके पास एक तर्क क्षेत्र में एक चर है जिसे बहुत बार निष्पादित किया जाता है, तो इसे स्थिर या वैश्विक बनाने पर विचार करें, क्योंकि अन्यथा आप हर बार एक छोटे से प्रदर्शन को ढीला कर देते हैं जो तर्क क्षेत्र में प्रवेश करते हैं, क्योंकि इसमें थोड़ा समय लगता है उस नए चर उदाहरण के लिए स्मृति आवंटित करें। आपको मेमोरी लोड और प्रदर्शन के बीच संतुलन खोजने की जरूरत है।
  3. संकलक द्वारा स्थिर विश्लेषण या अनुकूलन के लिए बेहतर लेआउट जैसे अन्य बिंदु भी खेल में आ सकते हैं।
  4. कुछ विशेष स्थितियों में, स्थैतिक तत्वों के अप्रत्याशित प्रारंभिक क्रम के साथ समस्या हो सकती है (उस बिंदु के बारे में निश्चित नहीं है, हालांकि इस लिंक की तुलना करें )।

स्रोत: arduino.cc पर समान धागा


आर-एंट्रेंस कभी भी Arduino पर एक मुद्दा नहीं होना चाहिए क्योंकि यह संगामिति का समर्थन नहीं करता है।
पीटर ब्लूमफील्ड

सच। यह एक सामान्य बिंदु से अधिक था, लेकिन वास्तव में Arduino के लिए प्रासंगिक नहीं था। मैंने उस बिट को हटा दिया।
फिलिप अल्गैर

1
एक दायरे के भीतर घोषित एक स्थिर चर हमेशा मौजूद रहेगा और एक वैश्विक चर के समान स्थान का उपयोग करेगा! ओपी कोड में, केवल अंतर यह है कि कोड किस चर को एक्सेस कर सकता है। स्काईप में स्टेटिक वील समान दायरे में पहुंच सकते हैं।
jfpoilpret

1
@jfpoilpret बेशक यह सच है, और मैं देख रहा हूं कि मेरे जवाब में संबंधित हिस्सा थोड़ा भ्रामक था। तय किया कि
फिलिप ऑलगाइर

2

दोनों चर स्थिर हैं - वे पूरे निष्पादन सत्र के लिए बने रहते हैं। वैश्विक किसी भी फ़ंक्शन के लिए दिखाई देता है अगर यह घोषित करता है - परिभाषित नहीं - वैश्विक, या यदि फ़ंक्शन एक ही संकलन इकाई में परिभाषा का पालन करता है (फ़ाइल + शामिल है)।

countकिसी फ़ंक्शन के अंदर की परिभाषा को आगे बढ़ाते हुए दोनों दृश्यता के अपने दायरे को {}es के निकटतम एन्क्लोजिंग सेट तक सीमित करते हैं , और यह फ़ंक्शन को आजीवन देता है (यह फ़ंक्शन में प्रवेश और बाहर निकलने के रूप में बनाया और नष्ट हो जाता है)। इसे घोषित करने के staticसाथ-साथ इसे निष्पादन सत्र भी दिया जाता है यह जीवनकाल के प्रारंभ से लेकर निष्पादन सत्र के अंत तक होता है, जो पूरे फ़ंक्शन इनवॉइस को जारी रखता है।

BTW: एक फ़ंक्शन के भीतर इनिशियलाइज़ किए गए स्टैटिक्स का उपयोग करने के बारे में सतर्क रहें, क्योंकि मैंने देखा है कि गन्न संकलक के कुछ संस्करणों को यह गलत लगता है। एक शुरुआती के साथ एक स्वचालित चर बनाया जाना चाहिए और प्रत्येक फ़ंक्शन प्रविष्टि पर प्रारंभ किया जाना चाहिए। एक प्रारंभिक के साथ एक स्थैतिक को केवल एक बार आरंभ किया जाना चाहिए, निष्पादन सेटअप के दौरान, मुख्य () से पहले नियंत्रण दिया जाता है (जैसा कि एक वैश्विक होगा)। मैंने स्थानीय स्टेटिक्स को प्रत्येक फ़ंक्शन प्रविष्टि पर पुन: व्यवस्थित किया है जैसे कि वे ऑटोमैटिक्स थे, जो गलत है। सुनिश्चित करने के लिए अपने स्वयं के संकलक का परीक्षण करें।


मुझे यकीन नहीं है कि मैं समझता हूं कि वैश्विक घोषित करने वाले फ़ंक्शन के बारे में आपका क्या मतलब है। क्या आपका मतलब है extern?
पीटर ब्लूमफील्ड

@ पीटरआर.ब्लूमफील्ड: मुझे यकीन नहीं है कि मेरी पोस्ट आपके किस हिस्से के बारे में पूछ रही है, लेकिन मैं ओपी के दो उदाहरणों का उल्लेख कर रहा था - पहला, एक स्वाभाविक रूप से वैश्विक परिभाषा और दूसरा, एक स्थानीय स्थैतिक।
JRobert

-3

Atmel के दस्तावेज के अनुसार: "यदि एक वैश्विक चर घोषित किया जाता है, तो SRAM में एक अद्वितीय पता प्रोग्राम लिंक समय के दौरान इस चर को सौंपा जाएगा।"

पूरा डॉक्यूमेंटेशन यहां है (वैश्विक चर के लिए टिप # 2): http://www.atmel.com/images/doc8453.pdf


4
क्या दोनों उदाहरण SRAM में एक अद्वितीय पते के साथ समाप्त होने वाले नहीं हैं? उन्हें दोनों को बनाए रखने की जरूरत है।
Cybergibbons

2
हाँ वास्तव में आप टिप # 6 में एक ही दस्तावेज़ में वह जानकारी पा सकते हैं
jfpoilpret
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.