如果你懂一点点的编译器的知识我想你都会知道编译器在编译你的代码的时候,用进行自动优化的,用以产生优化指令。同上操作系统和一些线程同样也会对你所定义的一些变量做出一些你所不知道的更改。这样的更改我们称为,隐式修改,因为你不知道,编译器在什么情况下,在那里做出了优化,甚至你都不知道,或是不能肯定编译器到底有没有对你的代码做出优化。

直接看看下面的例子

#include <iostream>
void main()
{
int i=10;
int a = i;

printf("i= %d\n",a);

__asm {
mov dword ptr [ebp-4], 50h
}
//下面汇编语句的作用就是改变内存中i的值,但是又不让编译器知道,来隐式的修改了变量。
int b = i;
printf("i= %d\n",b);
}

然后,在调试版本(debug)模式运行程序,输出结果如下:
i = 10
i = 80

然后,在release版本模式运行程序,输出结果如下:
i = 10
i = 10

呵呵结果看到了吗?输出的结果明显表明,release模式下,编译器对代码进行了优化,第二次没有输出正确的i值。所以得出一个结论在VC中release模式编译代码时编译器会自动对你的代码来做起优化的。而调试版本(debug)模式下便不会。

废话说了好多啊呵呵 下面继续说说 volatile

下面,我们把 i的声明加上volatile关键字,看看有什么效果:

#include <iostream>
void main()
{
 volatile int i=10;
 int a = i;

 printf("i= %d\n",a);
 __asm {
  mov         dword ptr [ebp-4], 50h
 }

 int b = i;
 printf("i= %d\n",b);
}

这下你再在调试版本和release版本运行程序,看看输出结果是不是都是:
i = 10
i = 32

估计大家看到这里便会明白了,volatile 这个关键字最最主要的意思是做什么的了。

在MSDN中volatile是一个限定符,也称为keyword或描述符,"volatile 关键字指示字段可由操作系统、硬件或并发执行的线程在程序中进行修改。"

当要求使用volatile 声明的变量的值的时候,系统总是重新从它所在的内存读取数据,即使它前面的指令刚刚从该处读取过数据。而且读取的数据立刻被保存。

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

1、中断服务程序中修改的供其它程序检测的变量需要加volatile;

2、多任务环境下各任务间共享的标志应该加volatile;

3、存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能由不同意义; 

声明方式为  volatile declaration

备注
系统总是在 volatile 对象被请求的那一刻读取其当前值,即使上一条指令从同一对象请求值。而且,该对象的值在赋值时立即写入。

volatile 修饰符通常用于由多个线程访问而不使用 lock 语句来序列化访问的字段。使用 volatile 修饰符能够确保一个线程检索由另一线程写入的最新值。

备注部分由MSDN原文所说。

本文参考:关于volatile关键字的说明以及测试(作者:iwaswzq) 有关volatile (函数前加volatile) 和inline的用法(作者:kobefly)

Advertisements