c語言中volatile關鍵字是什麼含義怎麼辦呢

2021-07-12 09:38:18 字數 3271 閱讀 6742

1樓:影者東昇

c/c++ 中的 volatile 關鍵字和 const 對應,用來修飾變數,通常用於建立語言級別的 memory barrier。

volatile 關鍵字是一種型別修飾符,用它宣告的型別變數表示可以被某些編譯器未知的因素更改,比如:作業系統、硬體或者其它執行緒等。遇到這個關鍵字宣告的變數,編譯器對訪問該變數的**就不再進行優化,從而可以提供對特殊地址的穩定訪問。

宣告時語法:int volatile vint; 當要求使用 volatile 宣告的變數的值的時候,系統總是重新從它所在的記憶體讀取資料,即使它前面的指令剛剛從該處讀取過資料。而且讀取的資料立刻被儲存。

例如:1 volatile int i=10;

2 int a = i;

3 ...

4 // 其他**,並未明確告訴編譯器,對 i 進行過操作

5 int b = i;

volatile 指出 i 是隨時可能發生變化的,每次使用它的時候必須從 i的地址中讀取,因而編譯器生成的彙編**會重新從i的地址讀取資料放在 b 中。而優化做法是,由於編譯器發現兩次從 i讀資料的**之間的**沒有對 i 進行過操作,它會自動把上次讀的資料放在 b 中。而不是重新從 i 裡面讀。

這樣以來,如果 i是一個暫存器變數或者表示一個埠資料就容易出錯,所以說 volatile 可以保證對特殊地址的穩定訪問。注意,在 vc 6 中,一般除錯模式沒有進行**優化,所以這個關鍵字的作用看不出來。下面通過插入彙編**,測試有無 volatile 關鍵字,對程式最終**的影響:

輸入下面的**:

01 #include

0203 void main()

041516 int b = i;

17 printf("i = %d", b);

18 }

然後,在 debug 版本模式執行程式,輸出結果如下:

i = 10

i = 32

然後,在 release 版本模式執行程式,輸出結果如下:

i = 10

i = 10

輸出的結果明顯表明,release 模式下,編譯器對**進行了優化,第二次沒有輸出正確的 i 值。下面,我們把 i 的宣告加上 volatile 關鍵字,看看有什麼變化:

01 #include

0203 void main()

041213 int b = i;

14 printf("i = %d", b);

15 }

分別在 debug 和 release 版本執行程式,輸出都是:

i = 10

i = 32

這說明這個 volatile 關鍵字發揮了它的作用。其實不只是“內嵌彙編操縱棧”這種方式屬於編譯無法識別的變數改變,另外更多的可能是多執行緒併發訪問共享變數時,一個執行緒改變了變數的值,怎樣讓改變後的值對其它執行緒 visible。一般說來,volatile用在如下的幾個地方:

1) 中斷服務程式中修改的供其它程式檢測的變數需要加volatile;

2) 多工環境下各任務間共享的標誌應該加volatile;

3) 儲存器對映的硬體暫存器通常也要加volatile說明,因為每次對它的讀寫都可能由不同意義;

2.volatile 指標

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

修飾由指標指向的物件、資料是 const 或 volatile 的:

1 const char* cpch;

2 volatile char* vpch;

注意:對於 vc,這個特性實現在 vc 8 之後才是安全的。

指標自身的值——一個代表地址的整數變數,是 const 或 volatile 的:

1 char* const pchc;

2 char* volatile pchv;

注意:(1) 可以把一個非volatile int賦給volatile int,但是不能把非volatile物件賦給一個volatile物件。

(2) 除了基本型別外,對使用者定義型別也可以用volatile型別進行修飾。

(3) c++中一個有volatile識別符號的類只能訪問它介面的子集,一個由類的實現者控制的子集。使用者只能用const_cast來獲得對型別介面的完全訪問。此外,volatile向const一樣會從類傳遞到它的成員。

3. 多執行緒下的volatile

有些變數是用volatile關鍵字宣告的。當兩個執行緒都要用到某一個變數且該變數的值會被改變時,應該用volatile宣告,該關鍵字的作用是防止優化編譯器把變數從記憶體裝入cpu暫存器中。如果變數被裝入暫存器,那麼兩個執行緒有可能一個使用記憶體中的變數,一個使用暫存器中的變數,這會造成程式的錯誤執行。

volatile的意思是讓編譯器每次操作該變數時一定要從記憶體中真正取出,而不是使用已經存在暫存器中的值,如下:

volatile bool bstop = false;

(1) 在一個執行緒中:

while( !bstop )

bstop = false;

return;

(2) 在另外一個執行緒中,要終止上面的執行緒迴圈:

bstop = true;

while( bstop ); //等待上面的執行緒終止,如果bstop不使用volatile申明,那麼這個迴圈將是一個死迴圈,因為bstop已經讀取到了暫存器中,暫存器中bstop的值永遠不會變成false,加上volatile,程式在執行時,每次均從記憶體中讀出bstop的值,就不會死迴圈了。

這個關鍵字是用來設定某個物件的儲存位置在記憶體中,而不是暫存器中。因為一般的物件編譯器可能會將其的拷貝放在暫存器中用以加快指令的執行速度,例如下段**中:

...int nmycounter = 0;

for(; nmycounter<100;nmycounter++)

...在此段**中,nmycounter的拷貝可能存放到某個暫存器中(迴圈中,對nmycounter的測試及操作總是對此暫存器中的值進行),但是另外又有段**執行了這樣的操作:nmycounter -= 1;這個操作中,對nmycounter的改變是對記憶體中的nmycounter進行操作,於是出現了這樣一個現象:nmycounter的改變不同步。

2樓:qq號

關鍵字是一種型別修飾符,用它宣告的型別變數表示可以被某些編譯器未知的因素更改

3樓:

就是告訴編譯器所對應的變數時隨時可變的,不要給我優化了,就這麼簡單

幾個c語言關鍵字的翻譯

auto 自動.break 中斷 迴圈語句,開關語句裡用 case 情況 開關語句裡用 char 字元.const 常量.continue 繼續 迴圈語句裡用 default 預設 開關語句裡用 do 做迴圈.double 雙精度.else 否則.enum 列舉型.extern 外部.float 單...

再請教你問題,C語言中關鍵字需要區分大小寫嗎

c語言一共只有32個關鍵字,程式書寫形式自由,區分大小寫。c語言什麼時候需要注意大小寫的問題?c語言很靈活 編譯器會自動調整大小寫 除非是特定程式 定義變數名的時候c語言區分大小寫,所以就要注意下 關鍵字,字元型變數賦值。函式名 語言裡面大小寫有區分嗎?c語言裡面大小寫有區分。區別為 用途不同 編譯...

C語言的合法的關鍵字包括哪些,c語言提供的合法關鍵字有那些?

c語言的合法資料型別的關鍵字大體上分為 int 整型 float 單精度型 double 雙精度型 和char 字元型 除了這基本的4種型別外,還有一些資料型別的修飾符,有long 長整型 short 短型 signed 有符號型 和unsigned 無符號型 float是浮點型資料型別,用於儲存單...