【C语言深入】[002] valotile 关键字:
2015-10-15 15:57
369 查看
前言:拒绝CP粘帖
valotile 做什么用的? 为什么要用这个关键字,它可以修饰什么? 怎么用?什么情况下可以用,什么时候不可以?
1 用法1 编译器标识:
我们知道CPU在执行PC指针的时候,往往会从内存里面读取页数据到CPU寄存器执行,为了提高系统效率,CPU在内存数据页面没有被替换的情况下,为了提高速度当然是首选访问以及载入到CPU内置算术单元的寄存器页数据,然而,这样有一个问题,就是如果读取的RAM值是一个经常改变的值(或者说根本不是一个RAM值,而是和硬件相关的memoery mapping 过来的一个硬件数据暂存器),那么就会有一个问题,CPU读取的已经载入的页面的数据和正在改变的硬件寄存器的数据是不一致的。我们一直希望,CPU还是直接访问,一直访问这个memory
mapping的地址,而不是已经装载的数据,那怎么办?
valotile 就是这个目的,他是为编译器准备的,告诉编译器,这个变量是一个容易改变的变量,每次都需要你真的读取一次。这种情形下,我们一般在定义全局变量的各种数据结构的时候,都在前面加上这个关键字就好。
2 用法2 编译器优化:
还有一种情况可以用在任何暂存的堆栈函数里面,这时候,因为某些操作(尤其是硬件操作)例如,对某个硬件内存做读改写指令,需要连续写两次,编译器有的时候就会给优化了,认为你两次操作之间没有什么赋值,值应该不会变,在编译的时候,你写的第二次改写就直接屏蔽掉了,我们看汇编代码,就会发现,其实就是一次赋值,这就是编译器优化了。如果我们在这个变量前加上 valotile关键字,那么就不会优化掉这个赋值。
举例:
注意,在vc6中,一般调试模式没有进行代码优化,所以这个关键字的作用看不出来。下面通过插入汇编代码,测试有无volatile关键字,对程序最终代码的影响:
然后,在调试版本模式运行程序,输出结果如下:
i = 10
i = 32
然后,在release版本模式运行程序,输出结果如下:
i = 10
i = 10
输出的结果明显表明,release模式下,编译器对代码进行了优化,第二次没有输出正确的i值。
下面,我们把 i的声明加上volatile关键字,看看有什么变化:
分别在调试版本和release版本运行程序,输出都是:
i = 10
i = 32
这说明这个关键字发挥了它的作用!
【巴蒂案】上面的例子是典型的编译器优化了,之前的调试模式,显然编译器选项优化选项选取不是很严格,代码的冗余量也比较大。
在正式公布版本的时候,编译器选项优化打开,造成了语句被优化了。
所以,在编写驱动程序的时候,尤其要注意,此外,release版本和公测版本的不同也有可能不是软件的bug,只是编译器的作用罢了
2 用法3 多线程使用:
valotile 就是告诉编译器要访问我的这块内存,除了,硬件驱动里面的硬件寄存器容易被改写外。还有一种情况就是多进程多线程的应用下。
有些变量很可能被IPC的作用而更改了值,需要你CPU去认真读取。
这样在一些多线程的接口函数里面也许就会有:
interface_task(valatile Interface_Data); 类似的使用等等。
ref:
1 C语言中volatile关键字的学习
http://www.chinaitlab.com/c/skill/818190.html
2 百度词条
http://baike.baidu.com/view/608706.htm
本文基本上纯手写原创,转载请注明原地址,谢谢!!! 欢迎讨论: email to 28044280@QQ.com
valotile 做什么用的? 为什么要用这个关键字,它可以修饰什么? 怎么用?什么情况下可以用,什么时候不可以?
1 用法1 编译器标识:
我们知道CPU在执行PC指针的时候,往往会从内存里面读取页数据到CPU寄存器执行,为了提高系统效率,CPU在内存数据页面没有被替换的情况下,为了提高速度当然是首选访问以及载入到CPU内置算术单元的寄存器页数据,然而,这样有一个问题,就是如果读取的RAM值是一个经常改变的值(或者说根本不是一个RAM值,而是和硬件相关的memoery mapping 过来的一个硬件数据暂存器),那么就会有一个问题,CPU读取的已经载入的页面的数据和正在改变的硬件寄存器的数据是不一致的。我们一直希望,CPU还是直接访问,一直访问这个memory
mapping的地址,而不是已经装载的数据,那怎么办?
valotile 就是这个目的,他是为编译器准备的,告诉编译器,这个变量是一个容易改变的变量,每次都需要你真的读取一次。这种情形下,我们一般在定义全局变量的各种数据结构的时候,都在前面加上这个关键字就好。
2 用法2 编译器优化:
还有一种情况可以用在任何暂存的堆栈函数里面,这时候,因为某些操作(尤其是硬件操作)例如,对某个硬件内存做读改写指令,需要连续写两次,编译器有的时候就会给优化了,认为你两次操作之间没有什么赋值,值应该不会变,在编译的时候,你写的第二次改写就直接屏蔽掉了,我们看汇编代码,就会发现,其实就是一次赋值,这就是编译器优化了。如果我们在这个变量前加上 valotile关键字,那么就不会优化掉这个赋值。
举例:
注意,在vc6中,一般调试模式没有进行代码优化,所以这个关键字的作用看不出来。下面通过插入汇编代码,测试有无volatile关键字,对程序最终代码的影响:
#include <stdio.h> void main() { int i=10; int a = i; printf( "i= %d\n",a); //下面汇编语句的作用就是改变内存中i的值,但是又不让编译器知道 __asm { mov dword ptr [ebp-4], 20h } int b = i; printf("i= %d\n",b); }
然后,在调试版本模式运行程序,输出结果如下:
i = 10
i = 32
然后,在release版本模式运行程序,输出结果如下:
i = 10
i = 10
输出的结果明显表明,release模式下,编译器对代码进行了优化,第二次没有输出正确的i值。
下面,我们把 i的声明加上volatile关键字,看看有什么变化:
#include <stdio.h> void main() { volatile int i=10; int a = i; printf( "i= %d\n",a); __asm { mov dword ptr [ebp-4], 20h } int b = i; printf("i= %d\n",b); }
分别在调试版本和release版本运行程序,输出都是:
i = 10
i = 32
这说明这个关键字发挥了它的作用!
【巴蒂案】上面的例子是典型的编译器优化了,之前的调试模式,显然编译器选项优化选项选取不是很严格,代码的冗余量也比较大。
在正式公布版本的时候,编译器选项优化打开,造成了语句被优化了。
所以,在编写驱动程序的时候,尤其要注意,此外,release版本和公测版本的不同也有可能不是软件的bug,只是编译器的作用罢了
2 用法3 多线程使用:
valotile 就是告诉编译器要访问我的这块内存,除了,硬件驱动里面的硬件寄存器容易被改写外。还有一种情况就是多进程多线程的应用下。
有些变量很可能被IPC的作用而更改了值,需要你CPU去认真读取。
这样在一些多线程的接口函数里面也许就会有:
interface_task(valatile Interface_Data); 类似的使用等等。
ref:
1 C语言中volatile关键字的学习
http://www.chinaitlab.com/c/skill/818190.html
2 百度词条
http://baike.baidu.com/view/608706.htm
本文基本上纯手写原创,转载请注明原地址,谢谢!!! 欢迎讨论: email to 28044280@QQ.com
相关文章推荐
- C/C++内存管理详解 堆 栈
- VC++2005、VC2008中Release版本设置为可调试的设置方法
- 多线程的那点儿事(之C++锁)
- C++构造函数初始化列表与赋值
- C++ 基础题目
- 【C语言深入】[001] static 关键字:
- C++学习笔记(杂)
- C++STL学习(4)容器set和multiset
- 【C语言】快速排序优质算法的动态显示和字符串的快排
- C++ const用法
- C++第七课 函数2
- Qt C++中的关键字explicit
- 从Qt谈到C++(一):关键字explicit与构造函数
- 转【STL学习】堆相关算法详解与C++编程实现(Heap)
- C++数据类型的大小
- 【C语言】杨辉三角
- c语言基本数据类型short、int、long、char、float、double
- C语言之函数和程序结构
- 【转载】C++ STL中哈希表 hash_map介绍
- C++面试问题