कांस्टेबल और कांस्टेबल के बीच अंतर


89

यदि हम volatileहर बार नए मूल्य के
रूप में एक चर घोषित करते हैं यदि हम एक चर घोषित करते हैं constतो उस चर का मान नहीं बदला जाएगा

तो फिर const volatile int temp;
चर tempको ऊपर घोषित करने का क्या फायदा है ?
अगर हम घोषणा करते हैं तो क्या होगा const int temp?


आप const volatile int temp;ब्लॉक स्कोप (यानी अंदर { }) का उपयोग नहीं करेंगे, इसका वहां कोई उपयोग नहीं है।
MM

जवाबों:


145

const volatileकोड के रूप में चिह्नित एक वस्तु को बदलने की अनुमति नहीं दी जाएगी ( constयोग्यता के कारण एक त्रुटि उठाई जाएगी ) - कम से कम उस विशेष नाम / सूचक के माध्यम से।

volatileक्वालीफायर का मतलब है कि संकलक अनुकूलित नहीं कर सकते या वस्तु को पुन: व्यवस्थित करें पहुँच का हिस्सा है।

एक एम्बेडेड सिस्टम में, यह आमतौर पर हार्डवेयर रजिस्टरों तक पहुंचने के लिए उपयोग किया जाता है जिसे हार्डवेयर द्वारा पढ़ा और अपडेट किया जा सकता है, लेकिन लिखने के लिए कोई मतलब नहीं है (या लिखने के लिए एक त्रुटि हो सकती है)।

एक उदाहरण एक सीरियल पोर्ट के लिए स्थिति रजिस्टर हो सकता है। विभिन्न बिट्स इंगित करेंगे कि क्या एक चरित्र पढ़ने के लिए इंतजार कर रहा है या यदि संचारित रजिस्टर एक नए चरित्र को स्वीकार करने के लिए तैयार है (यानी; - यह खाली है)। इस स्थिति रजिस्टर के प्रत्येक पढ़ने के परिणामस्वरूप सीरियल पोर्ट हार्डवेयर में और क्या हुआ है, इसके आधार पर एक अलग मूल्य हो सकता है।

यह स्थिति रजिस्टर (विशेष हार्डवेयर कल्पना के आधार पर) को लिखने के लिए कोई मतलब नहीं है, लेकिन आपको यह सुनिश्चित करने की आवश्यकता है कि रजिस्टर के प्रत्येक पढ़ने से हार्डवेयर की वास्तविक रीड में परिणाम होता है - पिछले रीड विन से एक कैश्ड मान का उपयोग करना ' t आपको हार्डवेयर स्थिति में परिवर्तन के बारे में बताता है।

एक त्वरित उदाहरण:

unsigned int const volatile *status_reg; // assume these are assigned to point to the 
unsigned char const volatile *recv_reg;  //   correct hardware addresses


#define UART_CHAR_READY 0x00000001

int get_next_char()
{
    while ((*status_reg & UART_CHAR_READY) == 0) {
        // do nothing but spin
    }

    return *recv_reg;
}

यदि इन बिंदुओं को होने के रूप में चिह्नित नहीं किया गया था volatile, तो कुछ समस्याएं हो सकती हैं:

  • हालांकि लूप टेस्ट केवल एक बार स्टेटस रजिस्टर पढ़ सकता है, क्योंकि कंपाइलर यह मान सकता है कि जो कुछ भी उसने बताया है वह कभी नहीं बदलेगा (जबकि लूप टेस्ट या लूप में कुछ भी ऐसा नहीं है जो इसे बदल सके)। यदि आप UART हार्डवेयर में कोई वर्ण प्रतीक्षा में फ़ंक्शन में प्रवेश करते हैं, तो आप एक अनंत लूप में समाप्त हो सकते हैं जो एक चरित्र प्राप्त होने पर भी कभी नहीं रुका।
  • प्राप्त रजिस्टर के पढ़ने को कंपाइलर द्वारा लूप से पहले ले जाया जा सकता था - फिर से क्योंकि फ़ंक्शन में ऐसा कुछ नहीं है जो इंगित करता है कि *recv_regलूप द्वारा बदल दिया गया है, कोई कारण नहीं है कि इसे लूप में प्रवेश करने से पहले पढ़ा नहीं जा सकता है।

volatileक्वालिफायर सुनिश्चित इन अनुकूलन संकलक द्वारा नहीं किया जाता है।


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

39
  • volatile कंपाइलर को चर से संबंधित कोड का अनुकूलन नहीं करने के लिए कहेंगे, आमतौर पर जब हम जानते हैं कि इसे "बाहर" से बदला जा सकता है, उदाहरण के लिए दूसरे धागे से।
  • const कंपाइलर को बताएगा कि प्रोग्राम के लिए वैरिएबल की वैल्यू को मॉडिफाई करना मना है।
  • const volatileएक बहुत ही खास बात है कि आप शायद अपने जीवन (टीएम) में 0 बार उपयोग करते हैं। जैसा कि उम्मीद की जा रही है, इसका मतलब है कि कार्यक्रम चर के मूल्य को संशोधित नहीं कर सकता है, लेकिन मूल्य को बाहर से संशोधित किया जा सकता है, इस प्रकार चर पर कोई अनुकूलन नहीं किया जाएगा।

12
मैंने सोचा होगा कि volatileचर आमतौर पर वही होता है जब आप हार्डवेयर के साथ गड़बड़ करना शुरू करते हैं, अन्य थ्रेड्स के साथ नहीं। जहाँ मैंने देखा const volatileहै कि मेमोरी-मैप्ड स्टेटस रजिस्टर या लाइक जैसी चीजों में है।
मेरे सही जनन

2
बेशक, आप बिलकुल सही हैं, मल्टीथ्रेडिंग सिर्फ एक उदाहरण है, लेकिन केवल एक ही नहीं :)।
मिंगोस

25
यदि आप एम्बेडेड सिस्टम के साथ काम करते हैं तो आप इसे बहुत बार देखेंगे।
डैनियल ग्रिलो

28

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

निरंतरता एक वादा है जो आप मूल्य को बदलने के लिए नहीं करते हैं, न कि यह कि मूल्य नहीं बदला जाएगा।


9
प्लस एक यह इंगित करने के लिए कि constडेटा "स्थिर" नहीं है।
बोगदान अलेक्जेंड्रू

7

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

cantx.id = 0x10<<24 | CANID<<12 | 0;

... निरंतर मान को प्री-कॉम्पटिशन करके और तत्काल असेंबली इंस्ट्रक्शन का उपयोग करके या पास के स्थान से निरंतर लोड करने के लिए, ताकि कॉन्फिग फ्लैश क्षेत्र में मूल CANID मान के किसी भी अपडेट को अनदेखा कर दिया जाए। CANID को अस्थिर होना चाहिए।


7

सी में, कांस्टेबल और अस्थिर टाइप क्वालिफायर हैं और ये दोनों स्वतंत्र हैं।

मूल रूप से, const का अर्थ है कि मान प्रोग्राम द्वारा परिवर्तनीय नहीं है।

और अस्थिर का अर्थ है कि मूल्य अचानक परिवर्तन (संभवतः कार्यक्रम के बाहर से) के अधीन है।

वास्तव में, सी मानक वैध घोषणा के एक उदाहरण का उल्लेख करता है जो कि कास्ट और वाष्पशील दोनों है। उदाहरण है

"एक्सट्रीम कास्ट वाष्पशील int real_time_clock;"

जहाँ real_time_clock हार्डवेयर द्वारा परिवर्तनीय हो सकता है, लेकिन उसे बढ़ाया, या घटाया नहीं जा सकता है।

इसलिए हमें पहले से ही कांस्ट और अलग से व्यवहार करना चाहिए। इसके अलावा, इन प्रकार के क्वालीफायर के रूप में अच्छी तरह से संरचना, संघ, एनम और टाइपडिफ़ के लिए लागू होता है।


5

आप एक साथ कास्ट और अस्थिर का उपयोग कर सकते हैं। उदाहरण के लिए, यदि 0x30 को एक बंदरगाह का मूल्य माना जाता है जो केवल बाहरी परिस्थितियों द्वारा बदला जाता है, तो निम्नलिखित घोषणा आकस्मिक दुष्प्रभावों की किसी भी संभावना को रोक सकती है:

const volatile char *port = (const volatile char *)0x30;

4

constइसका मतलब है कि चर को c कोड द्वारा संशोधित नहीं किया जा सकता है, ऐसा नहीं है कि यह बदल नहीं सकता है। इसका अर्थ है कि कोई भी निर्देश चर को नहीं लिख सकता है, लेकिन इसका मूल्य अभी भी बदल सकता है।

volatileइसका मतलब है कि चर किसी भी समय बदल सकता है और इस प्रकार कोई भी संचित मूल्यों का उपयोग नहीं किया जा सकता है; चर की प्रत्येक पहुंच को उसके मेमोरी पते पर क्रियान्वित किया जाना है।

चूँकि प्रश्न "एम्बेडेड" टैग किया गया है और इसे दबाने tempवाला एक उपयोगकर्ता घोषित चर है, न कि हार्डवेयर-संबंधी रजिस्टर (क्योंकि ये आमतौर पर एक अलग। H फ़ाइल में संभाला जाता है), पर विचार करें:

एक एम्बेडेड प्रोसेसर जिसमें अस्थिर वाष्प-लेखन डेटा मेमोरी (RAM) और गैर-वाष्पशील रीड-ओनली डेटा मेमोरी होती है, उदाहरण के लिए वॉन-न्यूमैन आर्किटेक्चर में FLASH मेमोरी, जहां डेटा और प्रोग्राम स्पेस एक साझा डेटा और एड्रेस बस साझा करते हैं।

यदि आप const tempएक मान होने की घोषणा करते हैं (कम से कम यदि 0 से अलग है), तो संकलक चर को FLASH स्थान के एक पते पर असाइन करेगा, क्योंकि भले ही वह RAM पते को सौंपा गया हो, लेकिन प्रारंभिक मूल्य को संग्रहीत करने के लिए उसे अभी भी फ़्लैश मेमोरी की आवश्यकता है वैरिएबल, रैम को बनाते हुए अंतरिक्ष की बर्बादी करता है क्योंकि सभी ऑपरेशन केवल-पढ़ने के लिए होते हैं।

परिणामस्वरूप:

int temp;एक वैरिएबल है RAM में, स्टार्टअप पर 0 से शुरू हुआ (cstart), कैश्ड मान का उपयोग किया जा सकता है।

const int temp;संकलक समय में 0 पर आरंभीकृत (पढ़ें- ony) FLASH में संग्रहीत एक चर है, कैश्ड मान का उपयोग किया जा सकता है।

volatile int temp; एक वैरिएबल है RAM में, स्टार्टअप पर 0 से आरंभ किया गया (cstart), कैश्ड मान का उपयोग नहीं किया जाएगा।

const volatile int temp; संकलक समय में 0 में आरंभीकृत (पढ़ें- ony) FLASH में संग्रहीत एक चर है, कैश्ड मान का उपयोग नहीं किया जाएगा

यहाँ उपयोगी भाग आता है:

आजकल अधिकांश एंबेडेड प्रोसेसर में एक विशेष फ़ंक्शन मॉड्यूल के माध्यम से अपनी रीड-ओनली वाष्पशील मेमोरी में बदलाव करने की क्षमता होती है, जिसमें const int tempरनटाइम में केस को बदला जा सकता है, सीधे तौर पर नहीं। एक अन्य तरीके से कहा, एक फ़ंक्शन उस पते पर मूल्य को संशोधित कर सकता है जहां tempसंग्रहीत है।

एक व्यावहारिक उदाहरण tempडिवाइस सीरियल नंबर के लिए उपयोग करना होगा । पहली बार एम्बेडेड प्रोसेसर चलता है, temp0 (या घोषित मूल्य) के बराबर होगा और एक फ़ंक्शन इस तथ्य का उपयोग उत्पादन के दौरान एक परीक्षण चलाने के लिए कर सकता है और यदि सक्सेफुल, एक सीरियल नंबर सौंपा जा सकता है और इसके tempमाध्यम से मूल्य को संशोधित कर सकता है एक विशेष समारोह के। कुछ प्रोसेसरों के पास ओटीपी (वन-टाइम प्रोग्रामेबल) मेमोरी के साथ एक विशेष पता सीमा होती है।

लेकिन यहाँ अंतर आता है:

यदि const int tempएक बार के प्रोग्रामयोग्य सीरियल नंबर के बजाय एक परिवर्तनीय आईडी है और घोषित नहीं किया गया है volatile, तो एक कैश किया हुआ मूल्य अगले बूट को पूरा नहीं किया जा सकता है, जिसका अर्थ है कि नई आईडी अगले रिबूट को वैध नहीं हो सकती है, या इससे भी बदतर हो सकती है, कुछ फ़ंक्शन नए मूल्य का उपयोग कर सकते हैं, जबकि अन्य पुराने कैश्ड मान का उपयोग कर सकते हैं जब तक कि रिबूट न ​​हो। यदि const int tempआईएस घोषित किया जाता है voltaile, तो आईडी परिवर्तन तुरंत प्रभावी होगा।


वाह यह उत्तर लंबा है


2

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


1

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

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