gcc编译器优化给我们带来的麻烦???
gcc编译器优化给我们带来的麻烦???
今天看到一个很有趣的程序,如下:
1
2
3
4
5
6
7
8
9
|
int main() { const int a = 1; int *b = ( int *)&a; *b = 21; printf ( "%d, %d" , a, *b); return 0; } |
当我第一眼看到这个程序的时候,我想当然的认为输出结果是21, 21,但是我错了
一时很难理解,于是我又输出了它们的地址:
int main() { const int a = 1; int *b = ( int *)&a; *b = 21; printf ( "%d, %d" , a, *b); printf ( "\n%p, %p" , &a, &*b); return 0; } |
它们的地址是一样的,看到这里我更加的不解,于是我试着查看一下汇编代码。
int main() { const int a = 1; int *b = ( int *)&a; *b = 21; printf ( "%d" , a); return 0; } |
对应汇编代码如下:
这里得到的是at&t的汇编代码,与intel不同之处在于:
1,指令格式为:指令名称 元操作数 目的操作数
2,寄存器前加%
3,操作数前加$
4,0x4(%esp)为内存寻址,实际表示的是esp寄存器中的内容 + 4(如果不是很明白,望自行查找资料,本人知识有限)
我们首先看标号为1的行,对应c语句为const int a =1,这是把1放进地址为0x18(%esp)的地方,再来看标号2的地方,对应的printf语句,发现并没有引用地址为0x18(%esp)的地方的值,而是把1直接放到了0x4(%esp),然后输出。
所以个人认为,之所以会出现最开始的结果,是因为编译器给我们做了一些优化导致的。为了证明我的观点,我修改了程序:
int main() { int c = 1; const int a = c; int *b = ( int *)&a; *b = 21; printf ( "%d, %d" , a, *b); return 0; } |
输出结果为:
对应的汇编代码为:
在标号1处,我们可以确定a存放在0x14(%esp)的地方,在标号2处,对应的printf语句,此语句从右向左处理参数,2处理的是*b,3处理的是a,这时看到用的是地址,而不是直接用数值,同时看标号0处,我们是将c赋值1,再给a赋值时编译器用的是数值,并没有引用地址。
所以,个人猜测,编译器在这方面有一个优化功能:如果一个变量在定义时赋值常量,那么在引用它的时候,编译器会直接用该常量数值代替地址的引用来节省时间,但是也给我们带来了以外的麻烦。
这些都是个人的观点,希望各位指教!!!
gcc编译器优化给我们带来的麻烦???的更多相关文章
- 【转】C 编译器优化过程中的 Bug
C 编译器优化过程中的 Bug 一个朋友向我指出一个最近他们发现的 GCC 编译器优化过程(加上 -O3 选项)里的 bug,导致他们的产品出现非常诡异的行为.这使我想起以前见过的一个 GCC bug ...
- GCC 编译优化指南(转)
GCC 编译优化指南(转) http://www.jinbuguo.com/linux/optimize_guide.html 作者:金步国 版权声明 本文作者是一位开源理念的坚定支持者,所以本文虽然 ...
- GCC 编译优化指南
转自: http://www.jinbuguo.com/linux/optimize_guide.html GCC 编译优化指南 作者:金步国[www.jinbuguo.com] 版权声明 本文作者是 ...
- GCC编译优化指南【作者:金步国】
GCC编译优化指南[作者:金步国] GCC编译优化指南 作者:金步国 版权声明 本文作者是一位自由软件爱好者,所以本文虽然不是软件,但是本着 GPL 的精神发布.任何人都可以自由使用.转载.复制和再分 ...
- GCC 编译优化指南【转】
转自:http://www.jinbuguo.com/linux/optimize_guide.html 版权声明 本文作者是一位开源理念的坚定支持者,所以本文虽然不是软件,但是遵照开源的精神发布. ...
- gcc编译器命令使用详解
1.gcc包含的c/c++编译器gcc,cc,c++,g++,gcc和cc是一样的,c++和g++是一样的,(没有看太明白前面这半句是什么意思:))一般c程序就用gcc编译,c++程序就用g++编译 ...
- 在CentOS 7.2下升级gcc编译器的版本
默认情况下,CentOS 7.2预装的gcc版本是4.8.x,通过执行命令 gcc -v 可以看到,一般情况下这个版本的编译器已经满足需要了,但是某些特殊的时候为了支持C++更高的特性,需要对gcc编 ...
- GCC编译器编译链接
在gcc编译器环境下,常见的文件扩展名的含义如下: .c:C源程序,经过预编译后的源程序也为.c文件,它可以通过-E参数输出. .h:头文件 .s:经过编译得到的汇编程序代码,它可以通过-S参数输出. ...
- Linux安装gcc编译器详解
本人使用的是CentOS 6.5 64位系统,由于在安装系统的时候并没有勾选安装gcc编译器,因此需要自行安装gcc编译器. 使用yum安装gcc 对于配备了yum的Linux发行版而言,安装gcc编 ...
随机推荐
- iWatch # 初始化工程
iWatch --利用swift,开发iWatch手表小应用! 远程仓库,团队开发: $ git init $ git add . $ git commit -m “ProjectName” // p ...
- Java设计模式之装饰者模式
要实现装饰者模式,注意一下几点内容: 1.装饰者类要实现真实类同样的接口 2.装饰者类内有一个真实对象的引用(可以通过装饰者类的构造器传入) 3.装饰类对象在主类中接受请求,将请求发送给真实的对象(相 ...
- UVa 740 - Baudot Data Communication Code
称号:目前编码,他们shift键被按下,并提出,对应的两个编码,其中,2相应的编码shift操作. 给你适当的编码值.寻求相应的字符串. 分析:模拟.字符串. 简单题,标记shift的升降分类处理就可 ...
- Java多线程的~~~Lock接口和ReentrantLock使用
在多线程开发.除了synchronized这个keyword外,我们还通过Lock接口来实现这样的效果.由Lock接口来实现 这样的多线程加锁效果的优点是非常的灵活,我们不在须要对整个函数加锁,并且能 ...
- TextView随键盘弹出上移高度
很多时候我们都在为键盘遮挡了原本就不大的屏幕时而烦恼,特别是当用户处于编辑状态时,键盘下面的内容就看不见了,用户只能处于盲打状态了.现在有一种简单的解决办法,基本思路就是,添加通知.一直监听键盘事件, ...
- 高德地图教程_poi搜索和显示
通过高仿深圳的应用近期打算.UI我们已经做了,我见过APP查询界面.关闭网络也将是能够查询其指示数据被存储在数据库中,或者是第一网络,所有网站上的数据是好了.我想简单地使用查询地图提供了. 曾经是接触 ...
- VS2015预览
VS2015预览版体验 .NET开源了,JAVA颤抖吧...据说VS2015可以开发android,ios,wp应用程序了,还可以开发能运行在mac,linux上的ASP.NET网站,如果真是这样 ...
- js 实现自动换行
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- iPhone、iPad、iPadMini界面设计标准
一个:iPhone 4.0' Display: iPhone 5.iPhone 5S.iPhone 5C. 解析度:1136 * 960 设计标准參照下图iPhone5 3.5' Display: ...
- [译]JVM运行时数据区
(本篇文章翻译自JVM Run-Time Data Areas) 这是我阅读JVM规范的笔记,而且我画了一个图来帮助我理解. 1.每一个单独的线程(非共享的)的数据区 针对每一个单独的线程的数据区包括 ...