C語言中volatile關鍵字用法

2021-10-21 06:51:14 字數 2678 閱讀 1803

介紹volatile關鍵字之前我們先了解一下編譯器的優化。

快取記憶體:處理器讀取程式裡面的資料時,把一些訪問頻率比較高的資料,臨時儲存到暫存器(register)中,當需要取資料時,就會從 register 中取,而不是直接去從 memory(記憶體)中取,節約了時間,像這樣的過程,叫做快取記憶體。

volatile關鍵字(keywords)是一種型別修飾符(type qualifiers),volatile 的英文翻譯過來是 「易變的」 。用volatile宣告型別變數的時候,編譯器對訪問該變數的**就不再進行優化,從而可以提供對特殊位址的穩定訪問;如果不使用volatile進行宣告,則編譯器將對所宣告的語句進行優化。即volatile關鍵字影響編譯器編譯的結果,用volatile宣告的變數表示該變數隨時可能發生變化,與該變數有關的運算,不要進行編譯優化,以免出錯。

當使用volatile宣告變數值的時候,編譯器總是重新從它所在的原記憶體讀取資料,即使它前面的指令剛剛從該處讀取過資料。

1> 告訴compiler不能做任何優化

int *ip =...; //裝置位址

*ip = 1; //第乙個指令

*ip = 2; //第二個指令

以上程式被compiler可能做優化為:

int *ip = ...;

*ip = 2;

結果第乙個指令丟失。如果用volatile, compiler就不允許做任何的優化,從而保證程式的原意:

volatile int *ip = ...;

*ip = 1;

*ip = 2;

即使你要compiler做優化,它也不會把兩次付值語句間化為一,它只能做其它的優化。

2> 用volatile定義的變數會在程式外被改變,每次都必須從記憶體中讀取,而不能重複使用放在cache(快取記憶體)或暫存器中的備份。

一般說來,volatile用在如下的幾個地方:

一、 中斷服務程式中修改的供其它程式檢測的變數需要加volatile

static

int i=0;

intmain

(void)}

}/* interrupt service routine. */

void

isr_2

(void

)

程式的本意是希望isr_2中斷產生時,在main當中呼叫do_something函式,但是,由於編譯器判斷在main函式裡面沒有修改過i,因此可能只執行一次對從i到某暫存器的讀操作,然後每次if判斷都只使用這個暫存器裡面的「i副本」,導致do_something永遠也不會被呼叫。如果變數加上volatile修飾,則編譯器保證對此變數的讀寫操作都不會被優化(肯定執行)。此例中i也應該如此說明。

二、多工環境下各任務間共享的標誌應該加volatile

在編寫多執行緒的程式時,同乙個變數可能被多個執行緒修改,而程式通過該變數同步各個執行緒。

dword __stdcall threadfunc

(lpvoid signal)

該執行緒啟動時將intsignal 置為2,然後迴圈等待直到intsignal 為1 時退出。顯然intsignal的值必須在外部被改變,否則該執行緒不會退出。但是實際執行的時候該執行緒卻不會退出,即使在外部將它的值改為1,看一下對應的偽彙編**就明白了:

mov ax,signal 

label:

if(ax!=1)

goto label

對於c編譯器來說,它並不知道這個值會被其他執行緒修改。自然就把它cache在暫存器裡面。記住,c 編譯器是沒有執行緒概念的!這時候就需要用到volatile。volatile 的本意是指:這個值可能會在當前執行緒外部被改變。也就是說,我們要在threadfunc中的intsignal前面加上volatile關鍵字,這時候,編譯器知道該變數的值會在外部改變,因此每次訪問該變數時會重新讀取,所作的迴圈變為如下面偽碼所示:

label: 

mov ax,signal

if(ax!=1)

goto label

3、memory

三、 儲存器對映的硬體暫存器通常也要加volatile說明,因為每次對它的讀寫都可能有不同意義;

xbyte[2]=0x55;

xbyte[2]=0x56;

xbyte[2]=0x57;

xbyte[2]=0x58;

對外部硬體而言,上述四條語句分別表示不同的操作,會產生四種不同的動作,但是編譯器卻會對上述四條語句進行優化,認為只有xbyte[2]=0x58(即忽略前三條語句,只產生一條機器**)。如果鍵入volatile,則編譯器會逐一地進行編譯並產生相應的機器**(產生四條**)。

注意: 以上這幾種情況經常還要同時考慮資料的完整性(相互關聯的幾個標誌讀了一半被打斷了重寫),在1中可以通過關中斷來實現,2 中可以禁止任務排程,3中則只能依靠硬體的良好設計了。

c語言中volatile關鍵字

volatile關鍵字是一種型別修飾符,用它宣告的型別變數表示可以被某些編譯器未知的因素更改 比如 作業系統 硬體或者其它執行緒等。遇到這個關鍵字宣告的變數,編譯器對訪問該變數的 就不再進行優化,從而可以提供對特殊位址的穩定訪問。使用該關鍵字的例子如下 int volatile nvint 當要求使...

C語言中volatile關鍵字

一 前言 程式的優化 1 硬體級別上的優化 a.由於記憶體訪問速度遠不及cpu處理速度,為提高機器整體效能,在硬體上引入硬體快取記憶體cache,加速對記憶體的訪問。b.在現代cpu中指令的執行並不一定嚴格按照順序執行,沒有相關性的指令可以亂序執行,以充分利用cpu的指令流水線,提高執行速度。2 軟...

C語言中volatile關鍵字

1.編譯器優化介紹 由於記憶體訪問速度遠不及cpu處理速度,為提高機器整體效能,在硬體上引入硬體快取記憶體cache,加速對記憶體的訪問。另外在現代cpu中指令的執行並不一定嚴格按照順序執行,沒有相關性的指令可以亂序執行,以充分利用cpu的指令流水線,提高執行速度。以上是硬體級別的優化。再看軟體一級...