每個變量和其名字一樣善變,有時候它善變是發自內心的,有時候是外部因素決定的,只有volatile變量才會表里如一,因此獲得了專一王子的美譽。
volatile字面意思是易揮發、易變化的意思,它修飾的變量表示該變量的值很容易由于外部的因素而發生改變,強烈要求編譯器要老老實實的在每次對變量進行訪問時去內存里讀取。
舉個生活中的栗子:
你明天 有一個朋友要過生日,今天把要送的禮物打包好了,一般情況下,我們明天起來不需要再次打開驗證一下里面的禮物是否存在,因為我們知道,只要禮物的外包裝沒有動過,里面的東西應該也沒有動過。其實編譯器和人一樣聰明,為了提高效率也會玩省事,做優化。
如下面的例子:
編譯器掃描了代碼發現上面,第一行代碼將10賦給了整型變量a,之后a變量的值沒有再發生變化,在后面的第二行中,將a變量的值取出來賦給b,在第三行代碼里面將a變量的值賦給了c的時候,因為CPU訪問內存速度慢,編譯器為了提高效率,玩“省事”,直接將10賦給了c。
單從上面的代碼我們來看是沒有問題的,就如同從外包裝看生日禮物完好一樣。但是,如果上述代碼運行在多線程中,在一個線程上下文中沒有改變它的值,但是我們卻不能保證變量的值沒有被其他線程所改變,就好比是,生日禮物放在其他人那里保管,我們不敢100%的確定它里面的東西完好。當然這種數據不一致的機制不僅僅出現在多線程中,同樣在設備的狀態寄存器里也會存在。例如,網卡里的某狀態寄存器里的值是否為1表示是否有網絡數據到達,在當前時刻其值為1,不能代表下一時刻它的值還是1,它的值有外界決定,編譯器肯定不能在這種情況下玩“省事”,為了防止在類似的情況下編譯器玩省事,可以將這些變量聲明為volatile,這樣不管它的值有沒有變化,每次對其值進行訪問的時候,都會從內存里,寄存器了讀取,保證數據的一致、做到表里如一。
總結:
一個定義為volatile的變量是說這變量可能會被意想不到地改變,這樣,編譯器就不會去假設這個變量的值了。精確地說就是,優化器在用到這個變量時必須每次都小心地重新讀取這個變量的值,而不是使用保存在寄存器里的備份。下面是volatile變量的幾個例子:(1). 并行設備的硬件寄存器(如:狀態寄存器)(2). 一個中斷服務子程序中會訪問到的非自動變量(Non-automatic variables)(3). 多線程應用中被幾個任務共享的變量
(1). 一個參數既可以是const還可以是volatile嗎?解釋為什么。答:是的。一個例子是只讀的狀態寄存器。它是volatile因為它可能被意想不到地改變。它是const因為程序不應該試圖去修改它。(2). 一個指針可以是volatile 嗎?解釋為什么。答:是的。盡管這并不很常見。一個例子是當一個中服務子程序修該一個指向一個buffer的指針時。(3). 下面的函數有什么錯誤:
這段代碼的有個惡作劇。這段代碼的目的是用來返指針*ptr指向值的平方,但是,由于*ptr指向一個volatile型參數,編譯器將產生類似下面的代碼:
由于*ptr的值可能被意想不到地該變,因此a和b可能是不同的。結果,這段代碼可能返不是你所期望的平方值!正確的代碼如下:
-
C語言
+關注
關注
180文章
7598瀏覽量
136210 -
volatile
+關注
關注
0文章
45瀏覽量
13009
原文標題:專一的王子,C語言volatile關鍵字解析
文章出處:【微信號:gh_c472c2199c88,微信公眾號:嵌入式微處理器】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論