站長資訊網(wǎng)
        最全最豐富的資訊網(wǎng)站

        C/C++ 中 volatile 關鍵字詳解


        1、為什么用volatile?

        C/C++ 中的 volatile 關鍵字和 const 對應,用來修飾變量,通常用于建立語言級別的 memory barrier。這是 BS 在 “The C++ Programming Language” 對 volatile 修飾詞的說明:

        A volatile specifier is a hint to a compiler that an object may change its value in ways not specified by the language so that aggressive optimizations must be avoided.

        volatile 關鍵字是一種類型修飾符,用它聲明的類型變量表示可以被某些編譯器未知的因素更改,比如:操作系統(tǒng)、硬件或者其它線程等。遇到這個關鍵字聲明的變量,編譯器對訪問該變量的代碼就不再進行優(yōu)化,從而可以提供對特殊地址的穩(wěn)定訪問。聲明時語法:int volatile vInt; 當要求使用 volatile 聲明的變量的值的時候,系統(tǒng)總是重新從它所在的內存讀取數(shù)據(jù),即使它前面的指令剛剛從該處讀取過數(shù)據(jù)。而且讀取的數(shù)據(jù)立刻被保存。例如:

        volatile int i=10;  int a = i;  ...  // 其他代碼,并未明確告訴編譯器,對 i 進行過操作  int b = i;

        volatile 指出 i 是隨時可能發(fā)生變化的,每次使用它的時候必須從 i的地址中讀取,因而編譯器生成的匯編代碼會重新從i的地址讀取數(shù)據(jù)放在 b 中。而優(yōu)化做法是,由于編譯器發(fā)現(xiàn)兩次從 i讀數(shù)據(jù)的代碼之間的代碼沒有對 i 進行過操作,它會自動把上次讀的數(shù)據(jù)放在 b 中。而不是重新從 i 里面讀。這樣以來,如果 i是一個寄存器變量或者表示一個端口數(shù)據(jù)就容易出錯,所以說 volatile 可以保證對特殊地址的穩(wěn)定訪問。注意,在 VC 6 中,一般調試模式?jīng)]有進行代碼優(yōu)化,所以這個關鍵字的作用看不出來。下面通過插入?yún)R編代碼,測試有無 volatile 關鍵字,對程序最終代碼的影響,輸入下面的代碼:

        實例

        #include <stdio.h> void main() { int i = 10; int a = i; printf("i = %d", a); // 下面匯編語句的作用就是改變內存中 i 的值 // 但是又不讓編譯器知道 __asm { mov dword ptr [ebp4], 20h } int b = i; printf("i = %d", b); }

        然后,在 Debug 版本模式運行程序,輸出結果如下:

        i = 10  i = 32

        然后,在 Release 版本模式運行程序,輸出結果如下:

        i = 10  i = 10

        輸出的結果明顯表明,Release 模式下,編譯器對代碼進行了優(yōu)化,第二次沒有輸出正確的 i 值。下面,我們把 i 的聲明加上 volatile 關鍵字,看看有什么變化:

        實例

        #include <stdio.h> void main() { volatile int i = 10; int a = i; printf("i = %d", a); __asm { mov dword ptr [ebp4], 20h } int b = i; printf("i = %d", b); }

        分別在 Debug 和 Release 版本運行程序,輸出都是:

        i = 10  i = 32

        這說明這個 volatile 關鍵字發(fā)揮了它的作用。其實不只是內嵌匯編操縱棧”這種方式屬于編譯無法識別的變量改變,另外更多的可能是多線程并發(fā)訪問共享變量時,一個線程改變了變量的值,怎樣讓改變后的值對其它線程 visible。一般說來,volatile用在如下的幾個地方:

        • 1) 中斷服務程序中修改的供其它程序檢測的變量需要加 volatile;
        • 2) 多任務環(huán)境下各任務間共享的標志應該加 volatile;
        • 3) 存儲器映射的硬件寄存器通常也要加 volatile 說明,因為每次對它的讀寫都可能由不同意義;

        2、volatile 指針

        和 const 修飾詞類似,const 有常量指針和指針常量的說法,volatile 也有相應的概念:

        修飾由指針指向的對象、數(shù)據(jù)是 const 或 volatile 的:

        const char* cpch;  volatile char* vpch;

        注意:對于 VC,這個特性實現(xiàn)在 VC 8 之后才是安全的。

        指針自身的值——一個代表地址的整數(shù)變量,是 const 或 volatile 的:

        char* const pchc;  char* volatile pchv;

        注意:

        • (1) 可以把一個非volatile int賦給volatile int,但是不能把非volatile對象賦給一個volatile對象。
        • (2) 除了基本類型外,對用戶定義類型也可以用volatile類型進行修飾。
        • (3) C++中一個有volatile標識符的類只能訪問它接口的子集,一個由類的實現(xiàn)者控制的子集。用戶只能用const_cast來獲得對類型接口的完全訪問。此外,volatile向const一樣會從類傳遞到它的成員。

        3、多線程下的volatile

        有些變量是用 volatile 關鍵字聲明的。當兩個線程都要用到某一個變量且該變量的值會被改變時,應該用 volatile 聲明,該關鍵字的作用是防止優(yōu)化編譯器把變量從內存裝入 CPU 寄存器中。如果變量被裝入寄存器,那么兩個線程有可能一個使用內存中的變量,一個使用寄存器中的變量,這會造成程序的錯誤執(zhí)行。volatile 的意思是讓編譯器每次操作該變量時一定要從內存中真正取出,而不是使用已經(jīng)存在寄存器中的值,如下:

        volatile  BOOL  bStop  =  FALSE;

        (1) 在一個線程中:

        while(  !bStop  )  {  ...  }    bStop  =  FALSE;    return;    

        (2) 在另外一個線程中,要終止上面的線程循環(huán):

        bStop  =  TRUE;    while(  bStop  );  //等待上面的線程終止,如果bStop不使用volatile申明,那么這個循環(huán)將是一個死循環(huán),因為bStop已經(jīng)讀取到了寄存器中,寄存器中bStop的值永遠不會變成FALSE,加上volatile,程序在執(zhí)行時,每次均從內存中讀出bStop的值,就不會死循環(huán)了。

        這個關鍵字是用來設定某個對象的存儲位置在內存中,而不是寄存器中。因為一般的對象編譯器可能會將其的拷貝放在寄存器中用以加快指令的執(zhí)行速度,例如下段代碼中:

        ...    int  nMyCounter  =  0;    for(;  nMyCounter<100;nMyCounter++)    {    ...    }    ...

        在此段代碼中,nMyCounter 的拷貝可能存放到某個寄存器中(循環(huán)中,對 nMyCounter 的測試及操作總是對此寄存器中的值進行),但是另外又有段代碼執(zhí)行了這樣的操作:nMyCounter -= 1; 這個操作中,對 nMyCounter 的改變是對內存中的 nMyCounter 進行操作,于是出現(xiàn)了這樣一個現(xiàn)象:nMyCounter 的改變不同步。

        原文地址:https://www.cnblogs.com/yc_sunniwell/archive/2010/07/14/1777432.html

        贊(0)
        分享到: 更多 (0)
        網(wǎng)站地圖   滬ICP備18035694號-2    滬公網(wǎng)安備31011702889846號
        主站蜘蛛池模板: 久久精品一本到99热免费| 久久精品黄AA片一区二区三区| 亚洲精品一品区二品区三品区 | 免费人妻精品一区二区三区| 国产精品宾馆在线精品酒店| 亚洲精品无码久久毛片| 国自产精品手机在线观看视频| 国产精品影音先锋| 精品无码人妻一区二区免费蜜桃| 亚洲av无码国产精品色在线看不卡 | 青青青青久久精品国产h久久精品五福影院1421 | 精品国产热久久久福利| 久久久久四虎国产精品| 国产精品免费高清在线观看| 亚洲乱码日产精品a级毛片久久| 国产精品手机在线观看你懂的| 精品无人区麻豆乱码1区2区 | 日韩精品欧美激情国产一区| 国产这里有精品| 国产精品第一区第27页| 91在线手机精品超级观看| 欧美+亚洲+精品+三区| 国产精品视频网站你懂得| 国产精品免费一区二区三区四区| 久久国产亚洲精品无码| 久久精品国产亚洲AV电影| 欧洲精品99毛片免费高清观看| 亚洲精品无码久久千人斩| 亚洲av午夜国产精品无码中文字| 欧美精品亚洲精品日韩精品| 久久久久亚洲精品男人的天堂| 精品久久久无码中文字幕天天| 精品久久人人爽天天玩人人妻| 精品一区二区三区在线观看| 久久丝袜精品中文字幕| 无码精品蜜桃一区二区三区WW| 亚洲日韩国产精品乱| 亚洲av永久无码精品古装片| 十八18禁国产精品www| 精品人妻va出轨中文字幕| 国产精品高清一区二区三区|