关于volatile关键字

来源:互联网 发布:java编码哪个是中文的 编辑:程序博客网 时间:2024/06/06 17:22

    volatile:不稳定的,易变的。他的意思告诉我们他很善变,需要多多注意一下它的举动,所以在使用这个关键字的时候需要注意一下。其实这个关键字用的很少,很多人也不知道他是什么(确实是这样的,在面试的过程中被问到了这个,当时一脸的懵啊)

    这个关键字和const类似,都是用来修饰类型的,它所修饰的变量可以被某些编译器未知的因素更改,比如操作系统,硬件,线程等等,一旦使用了volatile关键字修饰,编译器对访问该变量的代码就不再进行优化,从而提供对特殊地址的稳定访问。我们都知道对于某些变量,若是他被多次使用,编译器就不会为它重复生成从地址读取数据的汇编代码,从而提高了效率,一般是用寄存器来保存它的值,下次使用的时候直接从寄存器取值,这样的优化在某些情况下肯定会出现问题的,假如我恶意搞个破坏啊,下面请看个例子吧

void test1(){int i = 10;int j = i;int k = i;}void test2(){volatile int i = 10;int j = i;int k = i;}
//VS2013下的代码,其汇编代码如下:


从其汇编代码看,完全一样。这应该是编译器(VS2013)的缘故吧,而且我使用的是Debug版本的,没有对代码进行优化。


下面我们通过汇编指令改变它,观察一下是否使用volatile有什么影响

void test3(){int i = 10;int a = i;printf("i = %d\n",i);//通过汇编命令改变__asm{mov  dword ptr[ebp-4],20h}int b = i;printf("i = %d\n",i);}void test4(){volatile int i = 10;int a = i;printf("i = %d\n", i);//通过汇编命令改变__asm{mov  dword ptr[ebp - 4], 20h}int b = i;printf("i = %d\n", i);}

//VS2013下debug和release版本的结果:

(Debug版)


(Release版)



//VC++6.0的结果如下:



可以看出,不同的编译器还是有一定的区别的,而且Debug和Release版本确实有差别,但是加过volatile修饰的话,结果应该是:10和32,VC++6.0的Debug和Ralease版本的结果都满足条件,VS2013的Debug版本没有出现预期的结果,Relase版本出现预期的版本了,这些跟编译器有关。

     我觉得基于volatile的特性,它在某些场合下可以使用:

1.volatile的这中访问属性可以用在多线程上面,在某些场合可以替代lock工作。

2.存储器映射的硬件寄存器需要使用volatile修饰

    我在《C语言深度剖析》上看到了这样的一个问题:const volatile int i = 10;这样的修饰有问题吗?

首先,const修饰的说明为只读的,不能修改。而volatile修饰则是告诉编译器不要优化,使它按照设计者的意图去执行。表面上看,一个不能变,一个易变,放到一起真的是矛盾了。其实这两个关键字是可以一起修饰的,加volatile修饰说明此变量容易被各种因素改变,再加上const修饰后提示我们本程序不应该试图去改变它,我个人觉得在这里两个关键字组合起来各有侧重点,并不矛盾。

0 0