关键字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;
}
相关文章
相关标签/搜索
本站公众号
   欢迎关注本站公众号,获取更多信息