C語言中volatile關鍵字的作用

2021-10-07 07:08:30 字數 2683 閱讀 9942

在看c語言基礎知識的時候看到了volatile關鍵字,不是很理解,所以查了資料,總結一下。

volatile譯為:易變的

volatile是乙個型別修飾符(type specifier),就像我們熟悉的const一樣,它是被設計用來修飾被不同執行緒訪問和修改的變數;volatile的作用是作為指令關鍵字,確保本條指令不會因編譯器的優化而省略,且要求每次直接讀值。

簡單地說就是防止編譯器對**進行優化。比如如下程式:

xbyte[2]=0x55;

xbyte[2]=0x56;

xbyte[2]=0x57;

xbyte[2]=0x58;

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

典型的例子

for(int i=0; i<100000; i++);
這個語句用來測試空迴圈的速度的

但是編譯器肯定要把它優化掉,根本就不執行

如果你寫成

for(volatile int i=0; i<100000; i++);
它就會執行了

volatile的本意是「易變的」

下面是volatile變數的幾個例子:

1)並行裝置的硬體暫存器(如:狀態暫存器)

2)乙個中斷服務子程式中會訪問到的非自動變數(non-automatic variables)

3)多執行緒應用中被幾個任務共享的變數

1)乙個引數既可以是const還可以是volatile嗎?解釋為什麼。

2)乙個指標可以是volatile 嗎?解釋為什麼。

3)下面的函式被用來計算某個整數的平方,它能實現預期設計目標嗎?如果不能,試回答存在什麼問題:

int square(volatile int *ptr)

下面是答案:

1)是的。乙個例子是唯讀的狀態暫存器。它是volatile因為它可能被意想不到地改變。它是const因為程式不應該試圖去修改它。

2)是的。儘管這並不很常見。乙個例子是當乙個中斷服務子程式修改乙個指向乙個buffer的指標時。

3)這段**是個惡作劇。這段**的目的是用來返指標ptr指向值的平方,但是,由於ptr指向乙個volatile型引數,編譯器將產生類似下面的**:

int square(volatile int* &ptr)//這裡引數應該申明為引用,不然函式體裡只會使用副本,外部沒法更改

由於ptr的值可能在兩次取值語句之間發生改變,因此a和b可能是不同的。結果,這段**可能返回的不是你所期望的平方值!正確的**如下:

long square(volatile intptr)

另外,還可能出現在debug版中看不出來,在release版中才顯現的問題:

#includevoid main(int argc,char *ar**)

int b = i;

printf("i=%d",b);

}

然後,在除錯版本模式執行程式,輸出結果如下:

i = 10

i = 32

然後,在release版本模式執行程式,輸出結果如下:

i = 10

i = 10

輸出的結果明顯表明,release模式下,編譯器對**進行了優化,第二次沒有輸出正確的i值。

我們把 i的宣告加上volatile關鍵字,看看有什麼變化:

#includevoid main(int argc,char *ar**)

int b = i;

printf("i=%d",b);

}

分別在除錯版本和release版本執行程式,輸出都是:

i = 10

i = 32

這說明這個關鍵字發揮了它的作用!

volatile應該解釋為「直接訪問原始記憶體位址」比較合適,「易變的」這種解釋簡直有點誤導人;

比如多執行緒的程式,共同訪問的記憶體當中,多個程式都可以操縱這個變數

你自己的程式,是無法判定何時這個變數會發生變化

還比如,他和乙個外部裝置的某個狀態對應,當外部裝置發生操作的時候,通過驅動程式和中斷事件,系統改變了這個變數的數值,而你的程式並不知道。

對於volatile型別的變數,系統每次用到他的時候都是直接從對應的記憶體當中提取,而不會利用cache當中的原有數值,以適應它的未知何時會發生的變化,系統對這種變數的處理不會做優化——顯然也是因為它的數值隨時都可能變化的情況。

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

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

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

3、儲存器對映的硬體暫存器通常也要加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的指令流水線,提高執行速度。以上是硬體級別的優化。再看軟體一級...