1. 程式人生 > >C語言學習及應用筆記之四:C語言volatile關鍵字及其使用

C語言學習及應用筆記之四:C語言volatile關鍵字及其使用

  在C語言中,還有一個並不經常使用但卻非常有用的關鍵字volatile。那麼使用volatile關鍵字究竟能幹什麼呢?接下來我將就此問題進行討論。

  一個使用volatile關鍵字定義變數,其實就是告訴編譯系統這變數可能會被意想不到地改變。那麼編譯時,編譯器就不會自作主張的去假設這個變數的值,而進行程式碼的優化了。確切的說就是,編譯器在編譯程式碼時,優化器每次遇到這個變數,都會到記憶體中重新讀取,而不會使用儲存在暫存器裡的備份來對程式碼進行優化。

  我們已經瞭解了volatile關鍵字的基本作用。那麼,在什麼情況下使用volatile關鍵字呢?一般說來,在如下的幾種情況通常會使用volatile關鍵字:

  • 在中斷服務程式中修改的,供其它程式檢測的變數,通常需要定義為volatile;
  • 在多工環境下,各任務間共享的標誌,通常也需要定義為volatile;
  • 儲存器對映的硬體暫存器通常也需要定義為volatile,因為每次對它的讀寫都可能有不同意義;

1)使用中斷改變物件值的情況

  我們在中斷服務程式中操作了某個物件,比如誰改變了一個變數的值。而在其它程式中我們希望通過這個變數值得改變去進行一些操作。在這個時候,我們使用或者不使用volatile關鍵字,可能得到截然不同的結果。

  如果我們將變數定義為:static int var=0; ,然後再中斷服務成勳中將其修改為:var=1,但是在另一函式中使用它但不會修改它,那麼編譯器會認為它沒有變化,從而直接使用暫存器中的副本。

  如果我們將變數定義為:volatile int var=0;,那麼結果就完全不同了,每次在函式中使用var變數時,都會重新讀取,而不會使用暫存器中的副本。

(2)多工共享標誌的情況

  多工共享時,其實也是一樣的,在一個任務中修改了一個物件後,在另一個物件中應用它,但編譯器並沒發現在該任務中對它有修改。由於訪問暫存器的速度要快過RAM,所以編譯器一般都會作減少存取外部RAM的優化。從而並不能響應在另一任務下的變化。

  在這種情況下,一般我們都需要使用volatile關鍵字來定義任務間共享的標識。

3)硬體暫存器記憶體對映的情況

  記憶體對映的情況是非常多的,比如我們將外設的暫存器對映到記憶體的某一段區域;再比如我們同過DMA方式將資料直接寫到記憶體中的某一段區域。

由於我們外部的資料都是直接進入了記憶體區域,而程式知識引用它的值。編譯器優化時可能就直接採用暫存器中的副本了。佷顯然這不是我們需要的結果,這時將這段記憶體對應的變數宣告為volatile,則可以保證我們的需求。

  綜上所述,我們說明了volatile關鍵字的常規用法。當然,我們也可以發現volatile關鍵字是會降低編譯器優化力度的,但它卻可以保證程式的正確性,所以在適合的地方使用volatile關鍵字是必要的。不過能不能用的好,還要看程式設計者的基本功。

歡迎關注: