关键字volatile

  它是被设计用来修饰被不同线程访问和修改的变量如果没有volatile,基本上会导致这样的结果:要么无法编写多线程程序,要么编译器失去大量优化的机会。

volatile的作用: 作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值.
简单地说就是防止编译器对代码进行优化.比如如下程序:
XBYTE[2]=0x55;
XBYTE[2]=0x56;
XBYTE[2]=0x57;
XBYTE[2]=0x58;
对外部硬件而言,上述四条语句分别表示不同的操作,会产生四种不同的动作,但是编译器就不能像对待纯粹的程序那样对上述四条语句进行优化,只认为XBYTE[2]=0x58(即忽略前三条语句,只产生一条机器代码)。如果键入volatile,则编译器会逐一的进行编译并产生相应的机器代码(四条).

  volatile的语法和const是一样的。但是volatile的意思是:“在编译器认识的范围外,这个数据可以改变”。不知何故,环境正在改变数据(可能通过多任务、多线程或者中断处理),所以,volatile告诉编译器不要擅自作出有关该数据的任何假定,优化期间尤其如此。

  就行建立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;
}

 

 

 

posted @ 2013-04-03 22:49  wiessharling  阅读(222)  评论(0编辑  收藏  举报