關鍵字volatile

  它是被設計用來修飾被不一樣線程訪問和修改的變量。若是沒有volatile,基本上會致使這樣的結果:要麼沒法編寫多線程程序,要麼編譯器失去大量優化的機會。多線程

volatile的做用: 做爲指令關鍵字,確保本條指令不會因編譯器的優化而省略,且要求每次直接讀值.
簡單地說就是防止編譯器對代碼進行優化.好比以下程序:
XBYTE[2]=0x55;
XBYTE[2]=0x56;
XBYTE[2]=0x57;
XBYTE[2]=0x58;
對外部硬件而言,上述四條語句分別表示不一樣的操做,會產生四種不一樣的動做,可是編譯器就不能像對待純粹的程序那樣對上述四條語句進行優化,只認爲XBYTE[2]=0x58(即忽略前三條語句,只產生一條機器代碼)。若是鍵入volatile,則編譯器會逐一的進行編譯併產生相應的機器代碼(四條).

  volatile的語法和const是同樣的。可是volatile的意思是:「在編譯器認識的範圍外,這個數據能夠改變」。不知何故,環境正在改變數據(可能經過多任務、多線程或者中斷處理),因此,volatile告訴編譯器不要擅自做出有關該數據的任何假定,優化期間尤爲如此。ide

  就行創建const對象同樣,程序猿也能夠創建volatile對象,甚至還能夠創建const volatile對象,這個對象不能被客戶程序猿改變。可是,能夠經過外部的代理程序改變。函數

#include "stdafx.h"

class Comm
{
    const volatile unsigned char byte;
    volatile unsigned char flag;
    enum { bufsize = 100 };
    unsigned char buf[bufsize];
    int index;

public:
    Comm();
    void isr() volatile;
    char read(int index) const;
};

Comm::Comm(): index(0), byte(0), flag(0)
{
}

void Comm::isr() volatile
{
    flag = 0;
    buf[index++] = byte;
    if(index >= bufsize) index = 0;
}

char Comm::read(int index) const
{
    if(index<0 || index>= bufsize) return 0;
    return buf[index];
}

int _tmain(int argc, _TCHAR* argv[])
{
    volatile Comm port;
    port.isr();// OK
    //port.read(0); //Error read() not volatile
    return 0;
}

就像const 同樣,咱們能夠對數據成員和函數成員和對象自己使用volatile,能夠對volatile對象調用volitile函數。優化

 

問題:1). 一個參數既能夠是const還能夠是volatile嗎?解釋爲何。線程

   2). 一個指針能夠是volatile 嗎?解釋爲何。
   3). 下面的函數被用來計算某個整數的平方,它能實現預期設計目標嗎?若是不能,試回答存在什麼問題:
int square(volatile int *ptr)
{
return *ptr * *ptr;
}
下面是答案:
1). 是的。一個例子是隻讀的狀態寄存器。它是volatile由於它可能被意想不到地改變。它是const由於程序不該該試圖去修改它。
2). 是的。儘管這並不很常見。一個例子是當一箇中斷服務子程序修改一個指向一個buffer的指針時。
3). 這段代碼是個惡做劇。這段代碼的目的是用來返指針*ptr指向值的平方,可是,因爲*ptr指向一個volatile型參數,編譯器將產生相似下面的代碼:
int square(volatile int *ptr)
{
int a,b;
a = *ptr;
b = *ptr;
return a * b;
}

因爲*ptr的值可能在兩次取值語句之間發生改變,所以a和b多是不一樣的。結果,這段代碼可能返不是你所指望的平方值!正確的代碼以下:設計

long square(volatile int *ptr)
{
int a;
a = *ptr;
return a * a;
}
相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息