2011-03-04 12 views
19

सी/सी ++ में अस्थिर कीवर्ड का उपयोग क्या है? एक चर volatile घोषित करने और इसे volatile के रूप में घोषित करने के बीच क्या अंतर है?अस्थिर कीवर्ड का उपयोग क्या है?

+1

इसके अतिरिक्त, [आपके कंपाइलर को यह मानने के लिए कि यह अस्थिर है] (http: // stackoverflow।कॉम/प्रश्न/642568/कैसे-करें-मैं-पता-अगर-जीसीसी-सहमत-वह-कुछ-अस्थिर है) कभी-कभी थोड़ा सा काम लेता है। –

+3

देखें: http://stackoverflow.com/questions/72552/c-when-has-the-volatile-keyword-ever-helped-you और http://stackoverflow.com/questions/4437527/why-do-we -use-volatile-keyword-in-c – dappawit

+0

[वोल्टाइल कीवर्ड] के संभावित डुप्लिकेट (http://stackoverflow.com/questions/5620281/volatile-keyword) – EJP

उत्तर

9

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

आईएसए कार्ड के दिनों में आईएसए कार्ड के दिनों में केवल एक बार जब आप बस से डेटा प्राप्त करने के लिए स्मृति पता पढ़ते थे। कंपाइलर में भी एक बग था जिसका अर्थ था अस्थिर काम नहीं किया!

यह भी कुछ समानांतर/mutli-थ्रेडेड कोड में उपयोगी हो सकता

+2

यह एम्बेडेड सिस्टम में भी अक्सर उपयोग किया जाता है जहां विभिन्न रजिस्ट्रार और डिवाइस होते हैं स्मृति पते पर मैप किया गया। – user470379

+1

हां, जिसकी मुझे आवश्यकता थी, 16 बिट आईएसए पर आपको उच्च/निम्न बाइट प्राप्त करने के लिए दो बार एक ही पता पढ़ना पड़ा। दुर्भाग्यवश एमएस सी ++ ने फैसला किया कि ये दो बाइट हमेशा बराबर थे! –

+0

'अस्थिर' क्रूड सिंक्रनाइज़ेशन प्राइमेटिव के लिए आवृत्ति का दुरुपयोग किया जाता है। हर बार जब आप किसी डिवाइस ड्राइवर के बाहर कीवर्ड 'अस्थिर' देखते हैं, तो आपको इसे 'बग' के रूप में पढ़ना चाहिए। यह लगभग ऐसा करने का सही तरीका नहीं है ... जब तक कि आप एक सिंक्रनाइज़ेशन आदिम के लेखक नहीं हैं। –

25

एक चर पर volatile क्वालीफायर संकलक कि जब भी आप इस चर का उपयोग, अपने मूल्य स्मृति से लोड किया जाना है बताता है, और है कि संकलक पिछले मूल्यों से इस मूल्य के बारे में कुछ भी नहीं मान सकता है।

तो यह उचित है जब भी ऐसी स्थितियां हों जहां एक चर के पास एक मूल्य हो सकता है जो वर्तमान "निष्पादन के धागे" (व्यापक अर्थ में) में पूर्ववत नहीं हो सकता है। इसमें शामिल हैं:

  • हार्डवेयर संकेत संचालकों
  • लाइव चर कि इस तरह के goto रूप अप्रत्याशित छलांग के बाद किया जाता है, switch/case, या, अधिक महत्वपूर्ण में
  • स्थिति चर, setjmp/longjmp पंजीकृत करता है।

volatile थ्रेड साझा चरों पर परमाणु पहुंच के लिए भी आवश्यक है (लेकिन पर्याप्त नहीं है!) जिस पर पहुंच म्यूटेक्स नहीं है। उस उद्देश्य के लिए volatile परमाणु पहुंच की गारंटी के लिए पर्याप्त साधन नहीं है, भले ही यह केवल पढ़ने के लिए है। इसके लिए, आपको सीपीयू के विशेष निर्देशों का उपयोग करना होगा जिन्हें वर्तमान सी मानक, सी 99 की सार मशीन द्वारा मॉडलिंग (या इंटरफेस्ड) नहीं किया गया है। अगले मानक, सी 1 एक्स, ऐसे प्राइमेटिव होने चाहिए।

+8

बढ़ाता है क्योंकि यह पर्याप्त नहीं है, वास्तव में यह आवश्यक नहीं है। यह सिर्फ मदद नहीं करता है। :-) –

+2

@ बो, यह उन विशेष निर्देशों के साथ जरूरी है जो मैं उल्लेख करता हूं, और कार्यों में मौजूद नए इंटरफेस द्वारा भी इसकी आवश्यकता होगी। –

-3

जब हम उस समय साधारण गैर अस्थिर चर का उपयोग करते हैं तो संकलक कोड को अनुकूलित करने का प्रयास करेगा, उदाहरण के लिए यदि आप b = a * a * a का उपयोग कर रहे हैं; तो यह बी = ए * 3 की तरह इस्तेमाल किया जाएगा; लेकिन जब आप चर "ए" घोषित करते समय अस्थिर कीवर्ड का उपयोग करते हैं, तो अनुकूलन "ए" के मान के लिए नहीं होता है, और प्रत्येक बार जब स्मृति स्मृति से प्राप्त किया जाएगा, क्योंकि अस्थिर क्वालीफायर अन्य हार्डवेयर की अनुमति देगा साथ ही वैरिएबल के मान को बदलने की प्रक्रिया।

+0

1) ए * ए * ए! = ए * 3, 2) volatile क्वालीफायर परिवर्तनीय बदलने की अनुमति देता है - यह केवल संकलक को चेतावनी देता है कि परिवर्तनीय कहीं और बदल गया हो सकता है। –

+0

@ क्रिस्टियनसेवरिन –

0

वोल्टाइल संकलक को बताता है कि चर के मान को आपके कोड के दायरे से बाहर के लिए बदल दिया जा सकता है।

{ 
int x; 
int y; 
} 

x और y का मूल्य दायरे के लिए, लेकिन मामले में सीमित हैं अगर हम कहीं बाहर से तो यह रूप में अस्थिर चिह्नित किया जाना चाहिए क्योंकि संकलक अस्थायी रजिस्टर में इन मूल्यों को रखने के लिए और हमेशा दे देंगे अपने मूल्य को संशोधित कर रहे संशोधित मूल्य देने के बजाय एक ही मूल्य।

तो ऐसे मामलों में अस्थिर का उपयोग उस विशेष चर के हाल के मूल्य को प्राप्त करने के लिए किया जाना चाहिए।

3

अस्थिरता संकलक को बताती है कि यह मान बदल सकता है और संकलक को इस पर कोई अनुकूलन नहीं करना चाहिए। इसका एक उदाहरण

/** port to read temperature **/ 
#define PORTBASE 0x40000000 

unsigned int volatile * const port = (unsigned int *) PORTBASE; 

for(;;) 
{ 
    if(*port == 300) 
    { 
    /** shutdown the system **/ 
    } 

} 

तो बंदरगाह अस्थिर नहीं है, तो संकलक समझेंगे कि मूल्य नहीं बदला जा सकता। यह * पोर्ट == 300 की जांच कभी नहीं करेगा। हालांकि, सेंसर के आधार पर मूल्य बदला जा सकता है। हम संकलक को बताने के लिए अस्थिर डालते हैं जो इस पर कोई अनुकूलन नहीं करता है। अंगूठे नियम स्मृति मैप किए गए रजिस्टरों का उपयोग करते समय, जिसका मूल्य परिस्थिति के आधार पर बदल सकता है, फिर अस्थिर कीवर्ड का उपयोग करें।

1

अधिकांश सी प्रोग्रामों के लिए, किसी ऑब्जेक्ट का उद्देश्य अंतिम निष्पादन संदर्भ ("थ्रेड", सीपीयू कोर इत्यादि) में कोड द्वारा लिखी गई अंतिम चीज़ को पकड़ना है। किसी ऑब्जेक्ट की सामग्री का ट्रैक रखने के लिए एक कंपाइलर का सबसे आसान तरीका भंडारण में स्थान आवंटित करना है, और उस चर के पढ़ने और लिखने के साथ उस भंडारण के पढ़ने और लिखने का इलाज करना है, लेकिन भंडारण स्वयं कोड के उद्देश्य का प्रतिनिधित्व नहीं करता है-- यह केवल अंत के साधनों का प्रतिनिधित्व करता है। unsigned x; दिया गया है, यदि एक कंपाइलर x+=3; x+6; देखता है, तो कोड उत्पन्न करने का सबसे आसान तरीका एक्स लाने, 3 जोड़ने, परिणाम को x में संग्रहीत करना होगा, फिर एक्स को ले जाना, 6 जोड़ें, और उस परिणाम को स्टोर करना होगा। इंटरमीडिएट लोड और स्टोर, हालांकि, केवल तभी आवश्यक होता है जब संकलक को यह नहीं पता कि एक ही प्रभाव को कैसे प्राप्त किया जाए। एक बेहतर संकलक दिया इस तरह के कोड अक्सर यह आसान बनाने के लिए बस विशेष रूप से में 9.

जोड़ने के लिए सक्षम हो जाएगा एम्बेडेड या सिस्टम कोड, तथापि, एक कार्यक्रम के उद्देश्य लोड हो रहा है और में कुछ भंडारण स्थानों से निश्चित मूल्यों के भंडारण के शामिल हो सकते हैं एक निश्चित अनुक्रम। कई वास्तविक-दुनिया मशीन हार्डवेयर रखने के द्वारा I/O निष्पादित करती हैं जो कुछ वस्तुओं के भार और स्टोर द्वारा ट्रिगर होती है, और प्रतिक्रिया में विभिन्न क्रियाएं करती है। उदाहरण के लिए, किसी ऑब्जेक्ट को असामान्य नहीं होगा जो सही परिस्थितियों में टर्मिनल के साथ पारित होने के लिए भेजे गए किसी भी चरित्र का कारण बनता है। 'एच' संग्रहित करना और फिर 'i' सेरटेक्स को, उदाहरण के लिए, Hi भेज सकता है। एक कंपाइलर होने से ऐसे अनुक्रमों को सरल या समेकित करने का प्रयास किया जाता है (उदा। 'एच' की दुकान को छोड़ने का निर्णय) कार्यक्रमों को बेकार प्रदान करेगा। एक volatile क्वालीफायर संकलक को इंगित करता है कि जब अधिकांश ऑब्जेक्ट्स में अधिकतर पहुंच को समेकित करने के लिए स्वतंत्र होगा, तो कुछ ऐसे हैं जिनके लिए इस तरह की पहुंच को लिखित रूप में ठीक से करने की आवश्यकता है। प्रभावी ढंग से, एक कल्पना कर सकता है कि प्रत्येक अदिश प्रकार के लिए (उदाहरण के लिए "अहस्ताक्षरित") वहाँ कार्यों

int volatile_load_unsigned(unsigned volatile *p); 
void volatile_store_unsigned(unsigned volatile *p, usigned value); 

जिसका व्यवहार संकलक की तरह कोड के बारे में कुछ भी नहीं है, और इस तरह जानता हैं:

extern volatile unsigned x; 
x+=3; 
x+=6; 

से व्याख्या की जाएगी बराबर के रूप में संकलक:

extern volatile int x; 
volatile_store_unsigned(&x, volatile_load_unsigned(&x)+3); 
volatile_store_unsigned(&x, volatile_load_unsigned(&x)+6); 

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

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

कुछ कंपाइलर लेखकों का मानना ​​है कि कंपेलरों का मानना ​​है कि उन्हें अस्थिर-योग्य वाले लोगों तक पहुंच करने से पहले गैर-योग्य चर में स्टोर जेनरेट करने की आवश्यकता नहीं है। निश्चित रूप से मानक की आवश्यकता नहीं होती है कि कार्यान्वयन इस बात को स्वीकार करते हैं कि एक अस्थिर चर को लिखने से क्रियाएं उत्पन्न हो सकती हैं जो अन्य चीजों को प्रभावित कर सकती हैं, लेकिन इसका मतलब यह नहीं है कि ऐसे संरचनाओं के लिए एक गुणवत्ता कंपाइलर जहां ऐसी संरचनाएं उपयोगी हो सकती हैं उन्हें समर्थन नहीं देना चाहिए। दुर्भाग्यवश, तथ्य यह है कि मानक के लेखकों ने उन व्यवहारों को अनिवार्य नहीं करना चाहते थे जो कुछ प्रणालियों पर उपयोगी होंगी, लेकिन दूसरों को नहीं, यह सुझाव दिया गया है कि संकलक लेखकों को उन व्यवहारों पर भी ऐसे व्यवहारों का समर्थन नहीं करना चाहिए जहां वे उपयोगी हैं।

ध्यान दें कि कुछ प्रोसेसर पर, यह सुनिश्चित करना कि एक सीपीयू एक निश्चित अनुक्रम में निर्देश निष्पादित करता है, यह सुनिश्चित करने के लिए पर्याप्त नहीं हो सकता है कि उस निर्देश के प्रभाव अनुक्रम में होते हैं। कुछ प्रोसेसर में कॉन्फ़िगरेशन विकल्प शामिल होते हैं ताकि मेमोरी के कुछ हिस्सों पर संचालन की गारंटी दी जा सके, भले ही इससे निष्पादन गति कम हो जाए, और कुछ प्रोसेसर में निष्पादन आदेश को नियंत्रित करने के अन्य साधन शामिल हैं, लेकिन ऐसे मुद्दे volatile से अलग हैं। गुणवत्ता कार्यान्वयन पर, volatile यह सुनिश्चित करेगा कि प्रोसेसर कम से कम सभी पढ़ने और लिखने के बारे में जागरूक हो, जो होने की आवश्यकता है; एक प्रोग्रामर को यह सुनिश्चित करने के लिए अतिरिक्त कदम उठाने की आवश्यकता हो सकती है कि प्रोसेसर वास्तव में उन्हें संकेत के रूप में निष्पादित करता है, लेकिन प्रोसेसर को सभी लंबित परिचालनों को पूरा करने से पहले कुछ और करने से पहले यह अच्छा नहीं होगा अगर संकलक ने प्रोसेसर को कुछ नहीं बताया है लिखित होने की जरूरत है।

0

अस्थिर संकलक को प्रतिबंधित करता है जो विशेष चर के उपयोग को अनुकूलित नहीं करता है जिसे कोड में अस्थिर घोषित किया जाता है।

अस्थिर के साथ या बिना यह

अस्थिर

int main()  
{  
    int a = 5; 

    while(a == 5) //compiler replace variable **'a'** with 5 as optimization purpose  
    {   
    } 

    if(a==5)//compiler replace **'a'** with 5 as optimization purpose  
    {  
    } 

    return 0;  
} 
ऊपर कोड संकलक में

बिना चर चर के बीच अंतर को लगता है कि चर का मूल्य 'एक' हमेशा 5 हो जाएगा , इसलिए संकलक सभी 'ए' को ऑप्टिमाइज़ेशन उद्देश्य के रूप में 5 के साथ प्रतिस्थापित करता है। अस्थिर

साथ

चर लेकिन कुछ चर के बाहर बीच में से बदला मूल्य है, तो यहां हम हमेशा कि Memory.For से सीधे चर मूल्य इस उद्देश्य हम अस्थिर का उपयोग पाने के लिए की जरूरत है।

volatile int a=5; 

while(a==5) //compiler will npt optimize the variable **'a'** and always get the value of **'a'** from Memory 
+0

"से सहमत हैं" * कंपाइलर वैरिएबल 'ए' को अनुकूलित करेगा और हमेशा मेमोरी * से 'ए' का मान प्राप्त करेगा "पहला भाग सत्य है, लेकिन दूसरा भाग नहीं है। उदाहरण के लिए, सीपीयू अभी भी स्मृति से पहुंच को बाईपास कर सकता है और यह लगभग सभी आधुनिक प्रणालियों पर होता है। –

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