每個(gè)變量和其名字一樣善變,有時(shí)候它善變是發(fā)自?xún)?nèi)心的,有時(shí)候是外部因素決定的,只有volatile變量才會(huì)表里如一,因此獲得了專(zhuān)一王子的美譽(yù)。
volatile字面意思是易揮發(fā)、易變化的意思,它修飾的變量表示該變量的值很容易由于外部的因素而發(fā)生改變,強(qiáng)烈要求編譯器要老老實(shí)實(shí)的在每次對(duì)變量進(jìn)行訪(fǎng)問(wèn)時(shí)去內(nèi)存里讀取。
舉個(gè)生活中的栗子:
你明天 有一個(gè)朋友要過(guò)生日,今天把要送的禮物打包好了,一般情況下,我們明天起來(lái)不需要再次打開(kāi)驗(yàn)證一下里面的禮物是否存在,因?yàn)槲覀冎?,只要禮物的外包裝沒(méi)有動(dòng)過(guò),里面的東西應(yīng)該也沒(méi)有動(dòng)過(guò)。其實(shí)編譯器和人一樣聰明,為了提高效率也會(huì)玩省事,做優(yōu)化。
如下面的例子:
編譯器掃描了代碼發(fā)現(xiàn)上面,第一行代碼將10賦給了整型變量a,之后a變量的值沒(méi)有再發(fā)生變化,在后面的第二行中,將a變量的值取出來(lái)賦給b,在第三行代碼里面將a變量的值賦給了c的時(shí)候,因?yàn)?a href="http://www.socialnewsupdate.com/v/tag/132/" target="_blank">CPU訪(fǎng)問(wèn)內(nèi)存速度慢,編譯器為了提高效率,玩“省事”,直接將10賦給了c。
單從上面的代碼我們來(lái)看是沒(méi)有問(wèn)題的,就如同從外包裝看生日禮物完好一樣。但是,如果上述代碼運(yùn)行在多線(xiàn)程中,在一個(gè)線(xiàn)程上下文中沒(méi)有改變它的值,但是我們卻不能保證變量的值沒(méi)有被其他線(xiàn)程所改變,就好比是,生日禮物放在其他人那里保管,我們不敢100%的確定它里面的東西完好。當(dāng)然這種數(shù)據(jù)不一致的機(jī)制不僅僅出現(xiàn)在多線(xiàn)程中,同樣在設(shè)備的狀態(tài)寄存器里也會(huì)存在。例如,網(wǎng)卡里的某狀態(tài)寄存器里的值是否為1表示是否有網(wǎng)絡(luò)數(shù)據(jù)到達(dá),在當(dāng)前時(shí)刻其值為1,不能代表下一時(shí)刻它的值還是1,它的值有外界決定,編譯器肯定不能在這種情況下玩“省事”,為了防止在類(lèi)似的情況下編譯器玩省事,可以將這些變量聲明為volatile,這樣不管它的值有沒(méi)有變化,每次對(duì)其值進(jìn)行訪(fǎng)問(wèn)的時(shí)候,都會(huì)從內(nèi)存里,寄存器了讀取,保證數(shù)據(jù)的一致、做到表里如一。
總結(jié):
一個(gè)定義為volatile的變量是說(shuō)這變量可能會(huì)被意想不到地改變,這樣,編譯器就不會(huì)去假設(shè)這個(gè)變量的值了。精確地說(shuō)就是,優(yōu)化器在用到這個(gè)變量時(shí)必須每次都小心地重新讀取這個(gè)變量的值,而不是使用保存在寄存器里的備份。下面是volatile變量的幾個(gè)例子:(1). 并行設(shè)備的硬件寄存器(如:狀態(tài)寄存器)(2). 一個(gè)中斷服務(wù)子程序中會(huì)訪(fǎng)問(wèn)到的非自動(dòng)變量(Non-automatic variables)(3). 多線(xiàn)程應(yīng)用中被幾個(gè)任務(wù)共享的變量
(1). 一個(gè)參數(shù)既可以是const還可以是volatile嗎?解釋為什么。答:是的。一個(gè)例子是只讀的狀態(tài)寄存器。它是volatile因?yàn)樗赡鼙灰庀氩坏降馗淖?。它是const因?yàn)槌绦虿粦?yīng)該試圖去修改它。(2). 一個(gè)指針可以是volatile 嗎?解釋為什么。答:是的。盡管這并不很常見(jiàn)。一個(gè)例子是當(dāng)一個(gè)中服務(wù)子程序修該一個(gè)指向一個(gè)buffer的指針時(shí)。(3). 下面的函數(shù)有什么錯(cuò)誤:
這段代碼的有個(gè)惡作劇。這段代碼的目的是用來(lái)返指針*ptr指向值的平方,但是,由于*ptr指向一個(gè)volatile型參數(shù),編譯器將產(chǎn)生類(lèi)似下面的代碼:
由于*ptr的值可能被意想不到地該變,因此a和b可能是不同的。結(jié)果,這段代碼可能返不是你所期望的平方值!正確的代碼如下:
-
C語(yǔ)言
+關(guān)注
關(guān)注
180文章
7632瀏覽量
141675 -
volatile
+關(guān)注
關(guān)注
0文章
46瀏覽量
13347
原文標(biāo)題:專(zhuān)一的王子,C語(yǔ)言volatile關(guān)鍵字解析
文章出處:【微信號(hào):gh_c472c2199c88,微信公眾號(hào):嵌入式微處理器】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
深入理解和實(shí)現(xiàn)RTOS_連載
51單片機(jī)C語(yǔ)言講義(譚浩強(qiáng))以及深入理解C指針
專(zhuān)一的王子,C語(yǔ)言volatile關(guān)鍵字解析
深入理解STM32
對(duì)棧的深入理解
為什么要深入理解棧
STM32編程:是時(shí)候深入理解棧了<一>

深入理解C語(yǔ)言:循環(huán)語(yǔ)句的應(yīng)用與優(yōu)化技巧

評(píng)論