C語言中volatile關鍵字的作用

阿槐發表於2020-11-08

volatile關鍵字

一.前言
 編譯器優化介紹:

由於記憶體訪問速度遠不及CPU處理速度,為提高機器整體效能,

1)在硬體上: 引入硬體快取記憶體Cache,加速對記憶體的訪問。另外在現代CPU中指令的執行並不一定嚴格按照順序執行,沒有相關性的指令可以亂序執行,以充分利用CPU的指令流水線,提高執行速度。

2)軟體一級的優化:一種是在編寫程式碼時由程式設計師優化,另一種是由編譯器進行優化。編譯器優化常用的方法有:將記憶體變數快取到暫存器。由於訪問暫存器要比訪問記憶體單元快的多,編譯器在存取變數時,為提高存取速度,編譯器優化有時會先把變數讀取到一個暫存器中;以後再取變數值時就直接從暫存器中取值。但在很多情況下會讀取到髒資料,嚴重影響程式的執行效果。

二.volatile詳解

1.原理作用

Volatile意思是“易變的”,應該解釋為“直接存取原始記憶體地址”比較合適。

“易變”是因為外在因素引起的,像多執行緒,中斷等;

C語言書籍這樣定義volatile關鍵字:volatile提醒編譯器它後面所定義的變數隨時都有可能改變,因此編譯後的程式每次需要儲存或讀取這個變數的時候,告訴編譯器對該變數不做優化,都會直接從變數記憶體地址中讀取資料,從而可以提供對特殊地址的穩定訪問。。如果沒有volatile關鍵字,則編譯器可能優化讀取和儲存,可能暫時使用暫存器中的值,如果這個變數由別的程式更新了的話,將出現不一致的現象。(簡潔的說就是:volatile關鍵詞影響編譯器編譯的結果,用volatile宣告的變數表示該變數隨時可能發生變化,與該變數有關的運算,不要進行編譯優化,以免出錯)

2.一般用處:

一般說來,volatile用在如下的幾個地方:
  1) 中斷服務程式中修改的供其它程式檢測的變數,需要加volatile;

當變數在觸發某中斷程式中修改,而編譯器判斷主函式裡面沒有修改該變數,因此可能只執行一次從記憶體到某暫存器的讀操作,而後每次只會從該暫存器中讀取變數副本,使得中斷程式的操作被短路。
  2) 多工環境下各任務間共享的標誌,應該加volatile;

在本次執行緒內, 當讀取一個變數時,編譯器優化時有時會先把變數讀取到一個暫存器中;以後,再取變數值時,就直接從暫存器中取值;當記憶體變數或暫存器變數在因別的執行緒等而改變了值,該暫存器的值不會相應改變,從而造成應用程式讀取的值和實際的變數值不一致 。
  3) 儲存器對映的硬體暫存器通常也要加volatile說明,因為每次對它的讀寫都可能由不同意義;

假設要對一個裝置進行初始化,此裝置的某一個暫存器為0xff800000。for(i=0;i< 10;i++) *output = i;前面迴圈半天都是廢話,對最後的結果毫無影響,因為最終只是將output這個指標賦值為9,省略了對該硬體IO埠反覆讀的操作。

3.幾個問題

1)一個引數既可以是const還可以是volatile嗎?

可以的,例如只讀的狀態暫存器。它是volatile因為它可能被意想不到地改變。它是const因為程式不應該試圖去修改它。

2) 一個指標可以是volatile 嗎?

可以,當一箇中服務子程式修改一個指向buffer的指標時。

注意:頻繁地使用volatile很可能會增加程式碼尺寸和降低效能,因此要合理的使用volatile。

相關文章