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编 ...
随机推荐
- NDMCDB数据库hang住故障分析 - cursor: pin S wait on X
问题描写叙述: 上午刚刚到办公室,就有监控人员邮件反馈,昨晚NDMCDB407数据库被重新启动过,让我分析一下数据库重新启动的原因.因为昨晚业务有版本号上线,所以短信警告关闭了,所以没有短信下发到我手 ...
- 管理员控制Windows Service
C# 以管理员方式启动Winform,进而使用管理员控制Windows Service 问题起因: 1,) 问题自动分析Windows服务在正常运行时,确实会存在程序及人为原因导致该服务停止.为了 ...
- 使用JFinal框架中Validator
Validator是JFinal框架中的校验组件,在Validator类中提供了我们经常使用的校验方法,而Validator本身实现了Interceptor接口,所以Validator也相当于一个拦截 ...
- 最流行的Node.js应用开发框架简介
最流行的Node.js应用开发框架简介 快速开发而又容易扩展,高性能且鲁棒性强.Node.js的出现让所有网络应用开发者的这些梦想成为现实.但是,有如其他新的开发语言技术一样,从头开始使用Node.j ...
- C语言库函数大全及应用实例十
原文:C语言库函数大全及应用实例十 [编程资料]C语言库函数大全及应用实例十 函数名: qsort 功 能: 使 ...
- JavaScript时间工具类
/** * JavaScript日期工具类 * @author ZhangLp */ /** * 获取当前月的第一天 */ function getCurrentMonthFirst(){ var d ...
- ichartjs 使用BUG,assign_scale:true 解决
今天纯属灌水,好久没灌水的. 最近使用了flotr2 和 ichartjs进行canvas图标的开发,都不能满足需求. 没办法,先将就用用吧.然后,既然其他大神推荐使用ichartjs,为了统一,我也 ...
- ASP.NET 5 Hello World
ASP.NET 5系列教程 (二):Hello World 本篇文章内容比较基础,主要是向大家展示如何创建一个 ASP.NET 5 工程,主要包含内容如下: 创建ASP.NET 5 工程 添加 T ...
- ural1519插头DP
1519. Formula 1 Time limit: 1.0 second Memory limit: 64 MB Background Regardless of the fact, that V ...
- openSUSE13.2安装Nodejs并更新到最新版
软件源中直接安装Nodejs即可 sudo zypper in nodejs 查看nodejs版本 sincerefly@linux-utem:~> node --version v0.10.5 ...