C++关键字volatile解析

来源:互联网 发布:js循环遍历json对象 编辑:程序博客网 时间:2024/06/05 09:02

    volatile在英文中的解释是“不稳定的”,也就是说用该关键字修饰的变量的值随时可能被改变。用它声明的类型变量表示可以被某些编译器未知的因素更改,比如:操作系统、硬件或者其它线程等。 volatile的本意是“易变的”,不过翻译成“直接存取原始内存地址”更为合适。“易变”是因为外在因素引起的,象多线程,中断等,并不是因为用volatile修饰了的变量就是“易变”了,假如没有外因,即使用volatile定义,它也不会变化。

     计算机中进行计算时,通常会将数据拷贝到寄存器中,因为CPU对寄存器的操作远快于对内存的操作。

    在变量没有使用volatile修饰时,如果在计算过程中没有对该变量所在的寄存器操作,计算机将认为该变量的值没有变化,于是他就直接从寄存器中取值进行操作,而不会从内存/变量的源地址中取值。

    但是,如果变量使用了volatile关键字,则表明该变量的值随时可能在编译器认知的范围之外被改变(例如在终端中被改变或者多任务、多线程)。而此时volatile关键字的作用就是告诉编译器,不能擅自作出关于变量的值未改变的假设,每次进行计算时都从新从变量的源地址中取值,而不是取存放在寄存器中的拷贝。

    volatile关键字的语法和const的语法一样。

    总之,关键字volatile作用是取消编译器对被修饰的变量的任何优化,当对该变量进行操作时每次都是从他的源地址中读写,而不是从暂存数据的寄存器中读取,即取消编译器对此变量的优化。

    下面是几个例子:

例子1、

void delay(int time)

{

for(;time>0;time--);

}

上面这段代码本意是实现一个非精确的延时操作,通常来说没有什么问题,但是为了优化代码,打开了编译器的优化功能之后,这个函数将会被优化掉。因为,编译器发现这个函数实际上什么也没有做,为了提高性能编译器就会将这段代码优化掉。

为了防止被编译器优化掉,这段代码可以改成下面:

volatile void delay(int time)//这里用关键字volatile告诉编译器不要讲这段代码优化

{

for(;time>0;time--);

}

例子2、

float square(volatile float *ptr)

{

return *ptr * *ptr;

}

这段代码的问题在于形参使用了volatile关键字修饰,从而导致在调用这个函数的过程中*ptr的值可能被意外改变,其实它的过程如下

float square(volatile float *ptr)

{

float a, b;

a=*ptr;//在给a赋值之后,如果程序进入到中断中改变了*ptr的值,则b的值和a不同

b=*ptr;

return a * b;

}

以上代码应该改成:

float square(volatile float *ptr)

{

float a, b;

a=*ptr;

return a * a;

}

一般说来,volatile用在如下的几个地方:

  1. 中断服务程序中修改的供其它程序检测的变量需要加volatile;
  2. 多任务环境下各任务间共享的标志应该加volatile;
  3. 存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能由不同意义。

    另外,以上这几种情况经常还要同时考虑数据的完整性(相互关联的几个标志读了一半被打断了重写),在1中可以通过关中断来实现,2中可以禁止任务调度,3中则只能依靠硬件的良好设计了。



Motto: The world makes way for the man who knows where he is going.

 




原创粉丝点击