Volatile
Volatile 英文單詞的意思是不穩定的,反復無常的. 在C語言中用volatile的關鍵字聲明變量,就是說這個變量會發生意想不到的變化,每次用這個值的時候都需要重新去讀取. 精確的講應該是優化器用這個變量的時候每次都需要重新去讀取這個值,而不能用保存在寄存器裡的變量。這是編譯器優化器的副作用,因此有些變量要定義為volatile, 特別是在嵌入式編程中, 這是區分嵌入式工程師和C語言工程師之間最基本的一點
那什麼樣的變量需要是volatile類型呢?
硬件寄存器中斷處理程序訪問的非自動變量(靜態變量,全局變量)多線程共同訪問的變量再稍微深入的講一些,先提幾個問題
一個變量可以既是volatile又是const的嗎?why?指針可以使volatile的嗎?why?在講第一個問題的時候, 先說下const這個關鍵字
const: 一般人直接說它是常量,更精確的講法應該是只讀,很多函數傳入的是個const類型,就是防止你改變它。
const的作用:
一個參數是const就是為了告訴用戶這個參數的應用目的,給讀代碼的人傳達很有用的信息合理使用const可以使編譯器很自然地保護不希望被改變的參數,防止其被無意修改,減少了bug的出現回到正題: 答案是肯定的,一個變量既可以是const又是volatile,const 是指程序不應該去修改它,volatile是表明這個變量可能會發生意想不到的改變。只讀寄存器就可以是這樣的一個例子。
那個一個指針可以使volatile麼? 顯然是可以的,只是不大常見而已,指針可能會發生意想不到的改變,例如中斷程序中修改了一個指向buffer的指針
一個經典的面試題
int square(volatile int *ptr) { return *ptr * *ptr; }上面函數有問題嗎? 如果有,錯在哪裡,怎麼改?
square 函數的想法是求一個數的平方,但是*ptr可能會發生意向不到的改變,導致兩次讀出來的值不一樣,比如硬件寄存器的值,那麼這個函數返回的就不是一個數的平方了
對於上述函數編譯器產生的代碼類似於
int square(volatile int *ptr) { int a, b; a = *ptr; b = *ptr; return a * b; // a是第一次讀到的值,b是第二次讀到的值 }
int square(volatile int *ptr) { int a = *ptr; return a * a; }