c - सूचक स्थिर और साथ ही अस्थिर घोषित किया गया




const volatile (4)

उदाहरण के लिए अपने नेटवर्क कार्ड के केवल पढ़ने के लिए एक हार्डवेयर रजिस्टर पर विचार करें।

यह कार्यक्रम के नियंत्रण से बाहर बदल सकता है, इसलिए कंपाइलर को एक रजिस्टर में इसके मूल्य को कैश करने या इसे अनुकूलित करने की अनुमति नहीं है। इस प्रकार, volatile

और यह केवल पढ़ने के लिए है, इसलिए आपको इसे नहीं लिखना चाहिए। इस प्रकार, const

पढ़ते समय मैं इस प्रकार की घोषणा और निम्नलिखित पंक्ति में आया था -

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

P का मान केवल बाहरी स्थितियों से बदला जाता है

मुझे नहीं मिलता कि बाहरी परिस्थितियां क्या हैं। और यह भी कि इस प्रकार की घोषणा का व्यावहारिक उपयोग क्या है?


पहले, मुझे C11 मानक, अध्याय .36.7.3 से उदाहरण उद्धृत करते हैं, टाइप करें क्वालीफायर

घोषित की गई कोई वस्तु

extern const volatile int real_time_clock;

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

इसके अलावा, संबंधित फुटनोट (134),

मेमोरी-मैप्ड इनपुट / आउटपुट पोर्ट के अनुरूप ऑब्जेक्ट का वर्णन करने के लिए वाष्पशील घोषणा का उपयोग किया जा सकता है या एसिंक्रोनस रूप से बाधित फ़ंक्शन द्वारा एक्सेस की गई ऑब्जेक्ट। घोषित की गई वस्तुओं पर कार्रवाई एक "कार्यान्वयन द्वारा" अनुकूलित नहीं की जाएगी और अभिव्यक्ति का मूल्यांकन करने के लिए नियमों द्वारा अनुमति के अलावा पुन: व्यवस्थित की जाएगी।

इसका मतलब है, चर का मान हार्डवेयर (मेमोरी-मैपिंग के माध्यम से) द्वारा संशोधित किया जा सकता है, लेकिन "प्रोग्रामेटिक रूप से" संशोधित नहीं किया जा सकता है।

तो, लाभ यहाँ दो गुना है,

  • जब भी उपयोग किया जाने वाला मूल्य, मेमोरी से कैश किया जाएगा (कैश-आईएनजी की अनुमति नहीं है), आपको नवीनतम अद्यतन मूल्य (यदि अपडेट किया गया है) दे रहा है।
  • मान, परिवर्तित नहीं किया जा सकता ( लिखित रूप से ) प्रोग्राम द्वारा जानबूझकर या अनजाने में।

const एक वेरिएबल को स्थिर नहीं बनाता है। यह सिर्फ कंपाइलर को कुछ लिखने के लिए मना कर देता है। यह अभी भी चर (उदाहरण के लिए कास्ट-कास्ट पॉइंटर्स के माध्यम से) में लिखना संभव है।

आप const को कोडिंग गलतियों से सुरक्षा के रूप में देख सकते हैं।

यह घोषणा सुनिश्चित करती है कि आप अनजाने में p को नहीं लिखेंगे, जबकि संकलक को एक्सेस (कैश, ऑर्डर आउट से बाहर निकलने के लिए अनुकूलन नहीं) (), ...) को बताएं क्योंकि कोई बाहरी घटना p में लिख सकती है।


const कहता है कि आपके प्रोग्राम का प्रवाह p द्वारा इंगित किए गए को संशोधित करने वाला नहीं है। सूचक को निष्क्रिय करने के बाद मूल्य को संशोधित करने का कोई भी प्रयास एक संकलन-समय त्रुटि के परिणामस्वरूप होगा:

*p = 'A'; // will not compile

ध्यान दें कि यह एक विशेष रूप से मजबूत अनुबंध नहीं है; 0x30 स्थान पर मान अभी भी एक aliasing नॉन-कास्ट पॉइंटर के माध्यम से बदला जा सकता है, p :

volatile char *q = 0x30;
*q = 'A'; // will compile

इस कॉन्ट्रैक्ट को तोड़ने का एक और तरीका है कि p से const को दूर करके:

*(volatile char *) p = 'A'; // will compile

volatile , हालांकि, किसी भी संशोधन को बाहर नहीं करता है जो किसी अन्य धागे, कर्नेल, एक अतुल्यकालिक सिग्नल हैंडलर या एक बाहरी डिवाइस के कारण हो सकता है जिसकी समान मेमोरी स्पेस तक पहुंच है। इस तरह संकलक गलत धारणा नहीं बना सकता है कि p द्वारा p गए मूल्य में बदलाव नहीं होता है और इसे संदर्भित होने पर हर बार इसे मेमोरी से लोड किया जाएगा:

/*
 The character at 0x30 will be read on every iteration,
 even if the compiler has proven that the program itself
 doesn't modify the value at that address.
*/
while (*p) {
    ...
}

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





volatile