1. 程式人生 > >C語言中的volatile

C語言中的volatile

volatile的定義:

Indicates that a variable can be changed by a background routine.
Keyword volatile is an extreme opposite of const.It
 indicates that a variable may be changed in a way which is absolutely unpredictable by analysing the normal program flow (for example, a variable which may be changed by an interrupt handler). This keyword uses the following syntax:

翻譯為表示一個變數也許會被後臺程式改變,關鍵字 volatile 是與 const 絕對對立的。它指示一個變數也許會被某種方式修改,這種方式按照正常程式流程分析是無法預知的(例如,一個變數也許會被一箇中斷服務程式所修改)。

變數如果加上volatile,就會從記憶體中重新裝載內容,而不是從暫存器中拷貝內容。volatile 的作用 是作為指令關鍵字,確保本條指令不會因編譯器的優化而省略,且要求每次直接讀值。

volatile主要由一下幾種應用場合:

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

#define GPC1CON *((volatile unsigned int*)0xE0200080)
#define GPC1DAT *((volatile unsigned int*)0xE0200084)
#define GPC1PUD *((volatile unsigned int*)0xE0200088)
...........
 typedef const int32_t sc32;  /*!< Read Only */
  typedef const int16_t sc16;  /*!< Read Only */
  typedef const int8_t sc8;   /*!< Read Only */   typedef __IO int32_t  vs32;
typedef __IO int16_t  vs16;
typedef __IO int8_t   vs8; typedef __I int32_t vsc32;  /*!< Read Only */
typedef __I int16_t vsc16;  /*!< Read Only */
typedef __I int8_t vsc8;   /*!< Read Only */ typedef uint32_t  u32;
typedef uint16_t u16;
typedef uint8_t  u8; typedef const uint32_t uc32;  /*!< Read Only */
typedef const uint16_t uc16;  /*!< Read Only */
typedef const uint8_t uc8;   /*!< Read Only */ typedef __IO uint32_t  vu32;
typedef __IO uint16_t vu16;
typedef __IO uint8_t  vu8; typedef __I uint32_t vuc32;  /*!< Read Only */
typedef __I uint16_t vuc16;  /*!< Read Only */
typedef __I uint8_t vuc8;   /*!< Read Only * .............. #ifdef __cplusplus   #define   __I     volatile             /*!< defines 'read only' permissions                 */ #else
  #define   __I     volatile const       /*!< defines 'read only' permissions                 */
#endif
#define     __O     volatile             /*!< defines 'write only' permissions                */
#define     __IO    volatile             /*!< defines 'read / write' permissions              */

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

可以的,例如只讀的狀態暫存器。它是volatile因為它可能被意想不到地改變。它是const因為程式不應該試圖去修改它。軟體不能改變,並不意味著我硬體不能改變你的值,這就是微控制器中的應用。

 

2). 一箇中斷服務子程式中會訪問到的非自動變數(Non-automatic variables) 

/*   main.c */
int flag=0;
int main(void)
{
  if(flag==1)
    {do somethings}
  if(flag==2)
        {do somethings}
  return 0;
}
/* interrupt*/
void NVIC_Handler(void)
{
  flag=1;
}

在這種情況下,編譯器可能會對其做優化,雖然中斷服務函式改變了flag的值,但是編譯器並沒有在變數記憶體中去讀取,而是在暫存器中讀取了flag之前的快取資料。在中斷函式中的互動變數,一定要加上volatile關鍵字修飾,這樣每次讀取flag的值都是在其記憶體地址中讀取的,確保是我們想要的資料。


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

原因其實和上面中斷一樣,要共享標誌,又不想讓編譯器優化了這一點,需要加上該修飾詞。

 

簡潔的說就是:volatile關鍵詞影響編譯器編譯的結果,用volatile宣告的變量表示該變數隨時可能發生變化,與該變數有關的運算,不要進行編譯優化,以免出錯