易變數
volatile
關鍵字告訴編譯器,由於外部條件,變數的值可能隨時發生變化,而不僅僅是程式控制流的結果。
編譯器不會優化與 volatile 變數有關的任何內容。
volatile int foo; /* Different ways to declare a volatile variable */
int volatile foo;
volatile uint8_t * pReg; /* Pointers to volatile variable */
uint8_t volatile * pReg;
使用 volatile 變數有兩個主要原因:
- 與具有記憶體對映 I / O 暫存器的硬體介面。
- 使用在程式控制流程外修改的變數時(例如,在中斷服務程式中)
我們來看看這個例子:
int quit = false;
void main()
{
...
while (!quit) {
// Do something that does not modify the quit variable
}
...
}
void interrupt_handler(void)
{
quit = true;
}
允許編譯器注意 while 迴圈不修改 quit
變數並將迴圈轉換為無限的 while (true)
迴圈。即使在 SIGINT
和 SIGTERM
的訊號處理程式上設定了 quit
變數,編譯器也不知道。
將 quit
宣告為 volatile
將告訴編譯器不優化迴圈,問題將得到解決。
訪問硬體時會出現同樣的問題,如本例中所示:
uint8_t * pReg = (uint8_t *) 0x1717;
// Wait for register to become non-zero
while (*pReg == 0) { } // Do something else
優化器的行為是讀取變數的值一次,不需要重新讀取它,因為值總是相同的。所以我們最終得到了一個無限迴圈。為了強制編譯器執行我們想要的操作,我們將宣告修改為:
uint8_t volatile * pReg = (uint8_t volatile *) 0x1717;