volatile 限定符告知計算機,**(而不是變數所在的程式)可以改變該變數的值。
通常,它被用於硬體位址以及在其他程式或者同時執行的執行緒中共享資料。
例如,乙個位址上可能儲存著當前的始終時間,無論程式做什麼,位址上的值都隨著時間的變化而變化。或者乙個位址用於接受另一台計算機傳入的資訊。
volatile的語法和const一樣
volatile int locl;
//locl是乙個易變的量
volatile int* ploc
//ploc是乙個指向易變位置的指標
以上**把locl宣告為volatile變數,把ploc宣告為指向volatile變數的指標
vall = x;
//沒有用到x的**
val2 = x;
智慧型的編譯器回注意到以上的**使用了兩次x,但是並沒有改變其值。
於是編譯器把x的值臨時儲存在暫存器中,然後再val2
需要用x的時候,才從暫存器中(而不是原始記憶體位置上)讀取x的值,以節約的時間,這個過程被稱為快取記憶體(caching),通常,快取記憶體是乙個不錯的優化方案,但是如果一些其他**在以上兩條語句之間改變了x的值,就不能這麼優化了。
如果沒有volatile關鍵字,編譯器就不知道這種事情是否會發生。因此,為了安全起見,編譯器不會進行快取記憶體。
這是ansi之前的情況,現在,如果宣告中沒有volatile關鍵字,編譯器會假設變數的值在使用過程中保持不變。
可以同時使用const和volatile限定乙個值。
如,用const把硬體時鐘設定為程式不能更改的變數,但是可以通過**改變,這時候用volatile。只能夠在宣告中同時使用這個限定符,他們的順序不重要,如一下:
volatile const int loc;
const volatile int* ploc;
voliate關鍵字的應用場景
1、中斷服務程式中修改的供其它程式檢測的變數需要加volatile;
2、多工環境下各任務間共享的標誌應該加volatile;
3、儲存器對映的硬體暫存器通常也要加volatile說明,因為每次對它的讀寫都可能由不同意義。
(1)乙個引數既可以是const還可以是volatile嗎?為什麼?
是的。乙個例子是唯讀的狀態暫存器。它是volatile因為它可能被意想不到地改變。它是const因為程式不應該試圖去修改它。
(2)乙個指標可以是volatile嗎?為什麼?
是的。儘管這並不很常見。乙個例子是當乙個中服務子程式修該乙個指向乙個buffer的指標時。
(3)下面的函式有什麼錯誤?
int square(volatile int *ptr)
這段**有點**,其目的是用來返回指標ptr指向值的平方,但是,由於ptr指向乙個volatile型引數,編譯器將產生類似下面的**:
int square(volatile int *ptr)
由於*ptr的值可能被意想不到地該變,因此a和b可能是不同的。結果,這段**可能返回的不是你所期望的平方值!正確的**如下:
long square(volatile int *ptr)
詳解C中volatile關鍵字
volatile提醒編譯器它後面所定義的變數隨時都有可能改變,因此編譯後的程式每次需要儲存或讀取這個變數的時候,都會直接從變數位址中讀取資料。如果沒有volatile關鍵字,則編譯器可能優化讀取和儲存,可能暫時使用暫存器中的值,如果這個變數由別的程式更新了的話,將出現不一致的現象。下面舉例說明。在d...
詳解C中volatile關鍵字
volatile提醒編譯器它後面所定義的變數隨時都有可能改變,因此編譯後的程式每次需要儲存或讀取這個變數的時候,都會直接從變數位址中讀取資料。如果沒有volatile關鍵字,則編譯器可能優化讀取和儲存,可能暫時使用暫存器中的值,如果這個變數由別的程式更新了的話,將出現不一致的現象。下面舉例說明。在d...
詳解C中volatile關鍵字
來自 volatile提醒編譯器它後面所定義的變數隨時都有可能改變,因此編譯後的程式每次需要儲存或讀取這個變數的時候,都會直接從變數位址中讀取資料。如果沒有volatile關鍵字,則編譯器可能優化讀取和儲存,可能暫時使用暫存器中的值,如果這個變數由別的程式更新了的話,將出現不一致的現象。下面舉例說明...