volatile与编译器代码优化浅析
2015-07-18 13:14
337 查看
转载自:http://blog.chinaunix.net/uid-24641004-id-3395896.html
Volatile有什么用?
最近写ARM9的裸板C语言代码,比如说我想表示到GPBCON的地址的内容,我们往往会这样写:
#define GPBCON (*(volatile
unsigned int*)0x56000010)
这里的volatile关键字就是要告诉编译器,这个变量时经常改变的,而且编译时不要进行代码优化,所以每次读写的时候都要到它所在的地址去读取。这个对于一个寄存器地址来说非常重要,如果我们没有声明,很可能会给编译器进行编译优化,编译器生成的代码将不会是0x56000010这里读取,那么,如果我们的寄存器的状态变化了,我们的程序读取的地址却不是这个,那么就会出错。
关于编译器优化
为了提高运行效率,攻城湿们可是费尽心机地把代码优化,把程序运行时存取速度优化。一般,分为硬件优化和软件优化。硬件优化,流水线工作,详细可以参考《计算机组成原理》。
软件优化,一部分是程序猿们做的代码优化(前提你得有优化的思路和能力),还有一部分就是我们的编译器优化了。
现代的编译器经过那么多年的发展,已经比较成熟,把很多余的变量忽略掉,让代码的效率更高。而在默认情况下,编译器都会对代码进行优化,为了提高存取变量的速度,会把一些变量在寄存器里存取,而不是在内存里存取了,那这样CPU在自己家里拿东西当然比从内存那里拿东西要快得多。这样的情况一般我们在PC上写些入门级练习程序一般体验不到,但是对于学嵌入式,单片机的同学来说就是个不可忽视的问题。
如果写裸板程序时,我们对板的寄存器操作是不可避免的,但是如果我们没有用到volatile,那么这个板的寄存器的内容也被编译器默认编译到CPU的寄存器里读取,那么如果寄存器的状态发生改变了,我们能读到正确的状态吗?答案当然是否定的,我们这样只能读到CPU寄存器里的状态,而这个状态只是编译时就存在的,而CPU又没有再次读取内存了,所以这个状态是不变的,这是多么可怕的情况啊,我们触发一个外部中断都没有反应···
而是用volatile之后,编译器编译时就会明白,哦,这个变量很特殊,一定要到原来的地址去存取,不用把它优化,放在CPU寄存器里存取而是每次存取都从它原来的地址去读取。
那我们总结一下,什么时候会需要用到volatile这个关键字:
1 并行设备的硬件寄存器(如:状态寄存器)
2 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)
3 多线程应用中被几个任务共享的变量
也就是说,状态要经常变化的,为了防止我们编译优化而导致的存取的数据不同步的问题,这时我们就需要用到!
本文只是简单地介绍,如果想了解更多关于编译器具体怎么优化请看以下链接:
volatile关键字的作用:防止变量被编译器优化
http://witmax.cn/volatile.html
编译器优化
/article/4995259.html
浅析代码优化
/article/5140491.html
Volatile有什么用?
最近写ARM9的裸板C语言代码,比如说我想表示到GPBCON的地址的内容,我们往往会这样写:
#define GPBCON (*(volatile
unsigned int*)0x56000010)
这里的volatile关键字就是要告诉编译器,这个变量时经常改变的,而且编译时不要进行代码优化,所以每次读写的时候都要到它所在的地址去读取。这个对于一个寄存器地址来说非常重要,如果我们没有声明,很可能会给编译器进行编译优化,编译器生成的代码将不会是0x56000010这里读取,那么,如果我们的寄存器的状态变化了,我们的程序读取的地址却不是这个,那么就会出错。
关于编译器优化
为了提高运行效率,攻城湿们可是费尽心机地把代码优化,把程序运行时存取速度优化。一般,分为硬件优化和软件优化。硬件优化,流水线工作,详细可以参考《计算机组成原理》。
软件优化,一部分是程序猿们做的代码优化(前提你得有优化的思路和能力),还有一部分就是我们的编译器优化了。
现代的编译器经过那么多年的发展,已经比较成熟,把很多余的变量忽略掉,让代码的效率更高。而在默认情况下,编译器都会对代码进行优化,为了提高存取变量的速度,会把一些变量在寄存器里存取,而不是在内存里存取了,那这样CPU在自己家里拿东西当然比从内存那里拿东西要快得多。这样的情况一般我们在PC上写些入门级练习程序一般体验不到,但是对于学嵌入式,单片机的同学来说就是个不可忽视的问题。
如果写裸板程序时,我们对板的寄存器操作是不可避免的,但是如果我们没有用到volatile,那么这个板的寄存器的内容也被编译器默认编译到CPU的寄存器里读取,那么如果寄存器的状态发生改变了,我们能读到正确的状态吗?答案当然是否定的,我们这样只能读到CPU寄存器里的状态,而这个状态只是编译时就存在的,而CPU又没有再次读取内存了,所以这个状态是不变的,这是多么可怕的情况啊,我们触发一个外部中断都没有反应···
而是用volatile之后,编译器编译时就会明白,哦,这个变量很特殊,一定要到原来的地址去存取,不用把它优化,放在CPU寄存器里存取而是每次存取都从它原来的地址去读取。
那我们总结一下,什么时候会需要用到volatile这个关键字:
1 并行设备的硬件寄存器(如:状态寄存器)
2 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)
3 多线程应用中被几个任务共享的变量
也就是说,状态要经常变化的,为了防止我们编译优化而导致的存取的数据不同步的问题,这时我们就需要用到!
本文只是简单地介绍,如果想了解更多关于编译器具体怎么优化请看以下链接:
volatile关键字的作用:防止变量被编译器优化
http://witmax.cn/volatile.html
编译器优化
/article/4995259.html
浅析代码优化
/article/5140491.html
相关文章推荐
- java新手笔记4 数组
- c++Builder 2009 2010 出现Cannot convert 'wchar_t *' to 'const char *
- Java Web开发之:ModelDriven
- 整数实现翻转---java实现
- JAVA事件处理机制3
- Eclipse中离线安装ADT插件详细教程
- C语言中内存分布及程序运行中(BSS段、数据段、代码段、堆栈)
- Python字典key值查询效率低的问题
- 炼数成金(原 itpub 培训)
- fonts.googleapis.com, ajax.googleapis.com加载缓慢的解决方法
- Java连接数据库(JDBC)之三:java访问数据库MySQL实例
- eclipse关联androidSDK源码方法附带下载地址
- c# XML和实体类之间相互转换(序列化和反序列化)
- C和指针第九章课后习题编程练习
- C语言简单实现计算字符个数的方法
- C++内存管理
- java事件处理机制的核心
- java中数组的3中初始化方法
- thinkphp的知识点
- PHP+MYSQL如何插入记录到数据库