volatile

volatile是一個類型修飾符。它是被設計用來修飾被不一樣線程訪問和修改的變量。緩存

volatile的做用:做爲指令關鍵字,確保 本條指令不會因編譯器的優化而省略,且要求 每次直接讀值。它代表修飾的變量可能會被意料不到的改變。
讀取一個變量時,爲提升存取速度,編譯器優化時有時會先把變量讀取到一個寄存器中,之後再讀取變量值時,就直接從存儲器中取值。當變量值在本線程改變時,會同時copy到該寄存器中,以便保持一致。當別的線程等改變了值,該寄存器不會相應改變,從而形成應用程序讀取的值和實際的不一致。volatile就能夠應付這種狀況。
 
問題1:一個參數既能夠是const還能夠是volatile嗎?爲何?
答:能夠。const含義爲」請作爲常量使用「,但並不是」確定是個常量「;volatile含義爲」這個值可能隨時變掉「,而並不是」你能夠修改這個值「。
例如
int n = 9;
const int *pn = &n;

 

 
pn不能直接修改,可是能夠修改n,pn指向也就會變化。
 
另一個例子在嵌入式系統中比較常見。不少嵌入式系統容許咱們訪問外部寄存器,該寄存器的地址多是0x0018,該寄存器的最低位可能表示設備狀態,1爲忙碌,0爲空閒。
#define GET_REG_VALUE(reg) (*reg) /* get register value */
const unsigned char *STATUS_REG = 0x0018; /* status register */
const unsigned char STATUS_BUSY = 0x01; /* busy bit */
while (GET_REG_VALUE(STATUS_REG) & STATUS_BUSY); /* wait until free */
// do something to operate the device
...

 

 
這段代碼極可能會死循環。由於編譯器強姦民意的將地址0x0018處的值緩存起來,而後每次while的時候都從緩存中讀取。雖然STATUS_REG的值是const unsigned char *,但這僅僅表示STATUS_REG寄存器是個只讀寄存器,咱們不可以在代碼中去寫這個寄存器,但並不表示這個寄存器是不可以改變的。硬件完成了它的任務以後,就會把狀態設置成空閒,所以該寄存器的最後一位在咱們循環的時候極可能已經發生了變化。所以在這樣的地方,咱們要禁止編譯器自做聰明的優化,方法以下:
const volatile unsigned char *STATUS_REG = 0x0018; /* status register */
相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息