ZHCUAV8W january 1998 – march 2023 66AK2E05 , 66AK2H06 , 66AK2H12 , 66AK2H14 , AM1705 , AM1707 , AM1802 , AM1806 , AM1808 , AM1810 , AM5K2E04 , OMAP-L132 , OMAP-L137 , OMAP-L138 , SM470R1B1M-HT , TMS470R1A288 , TMS470R1A384 , TMS470R1A64 , TMS470R1B1M , TMS470R1B512 , TMS470R1B768
C/C++ 編譯器在所有模式下都支持 volatile 關鍵字,但 。此外,在 C89、C99、C11 和 C++ 的寬松 ANSI 模式下支持 __volatile 關鍵字。
volatile 關鍵字指示編譯器如何訪問變量,這要求編譯器不得投機取巧地優化涉及該變量的表達式。例如,外部程序、中斷、另一個線程或外圍設備也以訪問該變量。
編譯器會使用數據流分析來確定訪問是否合法,從而盡可能消除冗余的存儲器訪問。不過,一些存儲器訪問可能在編譯器未看到的方面比較特殊,在這類情況下,您應當使用 volatile 關鍵字來防止編譯器優化掉某些重要內容。對于已聲明為 volatile 的變量,編譯器不會優化掉對該變量的任何訪問。volatile 讀取和寫入的次數將與 C/C++ 代碼中的完全相同,不多不少而且順序也完全相同。
任何可能由明顯程序控制流程外部的事物(例如中斷服務例程)進行修改的變量必須聲明為 volatile。這會告訴編譯器,中斷函數可能會隨時修改該值,因此編譯器不應執行會更改該變量的編號或訪問順序的優化。這就是 volatile 關鍵字的主要用途。在下述示例中,循環旨在等待位置被讀取為 0xFF :
unsigned int *ctrl;
while (*ctrl !=0xFF);不過,在此示例中,*ctrl 是循環不變量表達式,因此循環會優化為單個存儲器讀取。若要獲取所需結果,應將 ctrl 定義為:
volatile unsigned int *ctrl;其中,*ctrl 指針旨在引用一個硬件位置,例如中斷標志。
訪問表示存儲器映射外圍設備的存儲器位置時,也必須使用 volatile 關鍵字。此類存儲器位置可能會以編譯器無法預測的方式更改值。這些位置可能會在被訪問時、或者當其他存儲器位置被訪問時或者出現某些信號時發生改變。
在調用 setjmp 的函數中,如果局部變量的值需要在發生 longjmp 時保持有效,則 volatile 也必須用于局部變量。
#include <stdlib.h>
jmp_buf context;
void function()
{
volatile int x = 3;
switch(setjmp(context))
{
case 0: setup(); break;
default:
{
/* We only reach here if longjmp occurs.因為 x 的生命周期在 setjmp 之前開始并持續至 longjmp,C 標準要求將 x 聲明為 "volatile"。*/
printf("x == %d\n", x);
break;
}
}
}