1.root@ubuntu:/home# gcc time.c -o p
2.root@ubuntu:/home# ./p
3.运行时间为:0.027647
使用了优化的运行结果为:
1.root@ubuntu:/home# gcc -o p time.c -O2
2.root@ubuntu:/home# ./p
3.运行时间为:0.027390
我们发现此时此刻不管是否使用优化语句运行,时间几乎没有变化,只是有微小的差异,这微小的差异是由于计算机本身所导致的。所以我们通过对于上面一个没有使用volatile和下面一个使用了volatile的对比结果可知,使用了volatile的变量在使用优化语句是for()循环并没有得到优化,因为for()循环执行的是一个空操作,那么通常情况下使用了优化语句使得这个for()循环被优化掉,根本就不执行。就好比编译器在编译的过程中将i的值设置为大于或者等于10000000的一个数,使得for()循环语句不会执行。但是由于我们使用了volatile,使得编译器就不会自作主张的去动我们的i值,所以循环体得到了执行。举这个例子的原因是要让读者牢记,如果我们定义了volatile变量,那么它就不会被编译器所优化。
当然volatile还有那些值得注意的地方呢?由于访问寄存器的速度要快过直接访问内存的速度,所以编译器一般都会作减少对于内存的访问,但是如果将变量加上volatile修饰,则编译器保证对此变量的读写操作都不会被优化。这样说可能有些抽象了,再看看下面的代码,在此就简要的写出几步了。
main()
{
int i=o;
while(i==0)
{
……
}
}
分析以上代码,如果我们没有在while循环体结构里面改变i的值,编译器在编译的过程中就会将i的值备份到一个寄存器中,每次执行判断语句时就从该寄存器取值,那么这将是一个死循环,但是如果我们做如下的修改:
main()
{
int volatile i=o;
while(i==0)
{
……
}
}
我们在i的前面加上了一个volatile,假设while()循环体里面执行的是跟上一个完全一样的操作,但是这个时候就不能说是一个死循环了,因为编译器不会再对我们的i值进行"备份"操作了,每次执行判断的时候都会直接从i的内存地址中读取,一旦其值发生变化就退出循环体。
最后给出一点就是在实际使用中volatile的使用的场合大致有以下几点:
1、中断服务程序中修改的供其它程序检测的变量需要加volatile;
2、多任务环境下各任务间共享的标志应该加volatile;
3、存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能有不同意义。