天天看點

C語言之volatile關鍵字

1.volatile關鍵字的介紹 

   volatile關鍵字是一種類型修飾符,用它聲明的類型變量表示可以被某些編譯器未知的因素更改,比如:作業系統、硬體或者其他線程等。遇到這個關鍵字聲明的變量,編譯器對通路該變量的代碼就不再進行優化,進而可以提供對特殊位址的穩定通路。

2.volatile關鍵字的用法

    當要求使用volatile關鍵字聲明的變量的時候,編譯器總是重新從它所在的記憶體讀取資料,即使它前面的指令剛剛從該處讀取過資料。而且讀取的資料立刻被儲存。

volatile int i = 10;
int a = 0;
int b = 0;

a = i;

//其它代碼并未明确告訴編譯器,對i進行過操作

b = i;
           

     volatile關鍵字指出i是随時可能發生變化的,每次使用它的時候必須從i的位址中讀取,是以編譯器會重新從i的位址讀取資料放在b中。而優化的做法是,由于編譯器發現兩次從i讀資料的代碼之間的代碼沒有對i進行過操作,它會自動把上次讀的資料放在b中。而不是重新從i裡面讀,這樣以來,如果i是一個寄存器變量或者表示一個端口資料就容易出錯,是以說volatile關鍵字可以保證對特殊位址的穩定通路。

     一個被volatile關鍵字聲明的變量可能會被意想不到的改變,編譯器在用到這個變量時必須每次都小心地重新讀取這個變量的值,而不是使用儲存在寄存器裡的備份。下面是使用到volatile關鍵字的情況:

     1)并行裝置的硬體寄存器(如:狀态寄存器)

     2)一個中斷服務子程式中會通路到的非自動變量

     3)多線程應用中被多個任務共享的變量。

3.volatile關鍵字的舉例說明

1)一個參數即可以是const還可以是volatile嗎?

可以。當它是一個隻讀的狀态寄存器。被volatile關鍵字聲明表示它可能被意想不到地改變。被const關鍵字聲明表示程式不應該去修改它。也就是說,const關鍵字指出我們的程式代碼中是不可以改變這個變量,但是volatile關鍵字指出由于硬體的原因,更改了這個值,但是我們的代碼同時會更新使用這個最新的數值。

2)一個指針變量可以聲明為volatile嗎?

可以。當一個中斷服務子程式修改一個指向一個buffer的指針時。(把指針聲明為volatile類型,可以保證指針所指向的位址随時發生變化)

3)下面所示的代碼是否正确?

int square(volatile int *ptr)
{
    return (*ptr * *ptr);
}
           

錯誤。這段代碼的作用是用來傳回指針*ptr指向值的平方,但是,由于*ptr指向一個volatile類型參數,編譯器産生類似下面的代碼:

int square(volatile int *ptr)
{
    int a = 0;
    int b = 0;

    a = *ptr;
    b = *ptr;
   
    return (a * b);
}
           

由于*ptr的值可能被意想不到的改變,是以a和b可能是不同的。結果,這段代碼可能傳回的不是你期望的平方值。正确代碼如下:

int square(volatile int *ptr)
{
    int a = 0;
    
    a = *ptr;

    return (a * a);
}
           

繼續閱讀