volatile影響編譯器編譯的結果。如果沒有volatile關鍵字,則編譯器可能優化讀取和存儲,即在本次線程內,當讀取一個變量時,為提高存取速度,編譯器優化時會先把變量讀取到一個寄存器中,以後再取變量值時,就直接從寄存器中取值。
volatile則提醒編譯器,用它所定義的變量隨時都有可能發生變化,因此編譯後的程序每次需要存儲或讀取這個變量的時候,都需要直接從變量地址中讀取數據。
【例14.20】分析下面函數能否實現延時的功能。
void delay (void ) { int i ; int result ; for (i=0 ; i < 1863 ; ++i ) result = 12* 35 ; }
【分析】不能。編譯器知道12*35的結果為420,因此他沒有做乘法而是通過優化處理直接給出「result=420」,從而關閉了計時功能。
如果使用兩個變量,及聲明
int num1 = 12 ,num2 = 35 ;
使用語句
result = num1 * num2 ;
也是不能實現計時的。一般與編譯器的選擇開關有關。這裡針對一般的情況,因為優化器知道儘管該函數計算了result的值,但它仍然沒有做任何處理。因此,無論result是否已經計算過,程序的執行都不會改變。於是,優化器發現如下循環:
for ( i=0 ; i < 1863 ; ++i ) { result = num1 * num2 ; }
就將其優化為:
for ( i=0 ; i < 1863 ; ++i ) { // Do nothing }
顯然,不需要將Do nothing重複420次,因此程序就被優化為:
// No loop needed { // Do nothing }
要阻止優化的方法是將result聲明為volatile。但這也沒有徹底解決問題,因為優化器很靈敏,它發現正在計算for循環體的
num1 * num2 ;
時,會把程序優化成只做一次乘法。
int register1 = num1 * num2 ; for ( i=0 ; i < 1863 ; ++i ) { result = register1 ; }
如果都使用volatile,就會克服這個問題。
// 修改後的程序 void delay (void ) { int i ; volatile int result ; volatile int num1 = 12 ; volatile int num2 = 35 ; for ( i=0 ; i < 1863 ; ++i ) { result = num1 * num2 ; } }