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修饰后提示我们本程序不应该试图去改变它,我个人觉得在这里两个关键字组合起来各有侧重点,并不矛盾。