BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / soft-design / #21496同步于 2007/10/1
该镜像源已超过 30 天没有更新,可能在源站已被删除。
SoftDesign机器人发帖

关于gcc优化选项,结果完全confusing...

ericyosho
2007/10/1镜像同步6 回复
写了一个很简单的测试代码。 #include <stdio.h> int main() { const int i = 1; int* p = (int*)&i; (*p)++; printf("%d %d\n", *p, i); printf("%p %p\n", p, &i); return 0; } 如果不加任何的-O选项,直接编译 gcc -o test.exe test.c 结果发现 i 的值也变为了2,说明const并没有起作用。 如果加了-O1选项,结果 i 的值仍然为1,此时两个地址却仍然是相同的,有点诡异。 然后按照man的解释,把-O1所对应的优化选项一个个显式地使用,像这样 gcc -fdefer-pop -fmerge-constants ... -o test.exe test.c 发现结果和不加优化选项时一样,难道写-O1和一个个显示写还有差别? 完全地被打败了……
订阅后,新回复会通过你的通知中心匿名送达。
6 条回复
Neverwinter机器人#1 · 2007/10/1
居然允许const转为非const?
ericyosho机器人#2 · 2007/10/1
是啊,故意这样转的,手册上也允许这样转的。 :-)
hman机器人#3 · 2007/10/2
你这样写 int* p = (int*)&i; 就是把const类型的常量属性去掉了吧。 我用了gcc和g++都编译了一下。 用gcc的结果和你说的一样,都是2。但是用g++的结果就是2 1。 我个人认为这个应该和编译器有关。 c语言中虽然也有const属性,但是这个属性是不是内部链接的。但在C++中const是一个内部链接的值。所以i的值是直接从符号表里去出的而不是从某内存地址取出的。 个人意见仅供参考。有待达人解释。
hman机器人#4 · 2007/10/2
我用objdump -Slz a.out 试了一下 看一下吧,虽然我也不怎么看的懂,还希望高人指点。 使用gcc的汇编代码如下: ----------------------------------------------------------------------------------------- 299 const int i = 1; 300 8048384: c7 45 fc 01 00 00 00 movl $0x1,0xfffffffc(%ebp) 301 int* p = (int*)&i; 302 804838b: 8d 45 fc lea 0xfffffffc(%ebp),%eax 303 804838e: 89 45 f8 mov %eax,0xfffffff8(%ebp) 304 (*p)++; 305 8048391: 8b 45 f8 mov 0xfffffff8(%ebp),%eax 306 8048394: ff 00 incl (%eax) 307 printf("%d %d\n", *p, i); 308 8048396: 83 ec 04 sub $0x4,%esp 309 8048399: ff 75 fc pushl 0xfffffffc(%ebp)这里c语言参数是地址 310 804839c: 8b 45 f8 mov 0xfffffff8(%ebp),%eax 311 804839f: ff 30 pushl (%eax) 312 80483a1: 68 ac 84 04 08 push $0x80484ac 313 80483a6: e8 05 ff ff ff call 80482b0 <printf@plt> 314 80483ab: 83 c4 10 add $0x10,%esp 使用g++的汇编代码如下 ----------------------------------------------------------------------- 385 const int i = 1; 386 804844c: c7 45 fc 01 00 00 00 movl $0x1,0xfffffffc(%ebp) 387 int* p = (int*)&i; 388 8048453: 8d 45 fc lea 0xfffffffc(%ebp),%eax 389 8048456: 89 45 f8 mov %eax,0xfffffff8(%ebp) 390 (*p)++; 391 8048459: 8b 45 f8 mov 0xfffffff8(%ebp),%eax 392 804845c: ff 00 incl (%eax) 393 printf("%d %d\n", *p, i); 394 804845e: 83 ec 04 sub $0x4,%esp 395 8048461: 6a 01 push $0x1在这里c++则是直接使用符号 396 8048463: 8b 45 f8 mov 0xfffffff8(%ebp),%eax 397 8048466: ff 30 pushl (%eax) 398 8048468: 68 90 85 04 08 push $0x8048590 399 804846d: e8 ba fe ff ff call 804832c <printf@plt> 400 8048472: 83 c4 10 add $0x10,%esp
jnds机器人#5 · 2007/10/2
各种版都发啊……
ericyosho机器人#6 · 2007/10/2
CL编译器也是将 i 直接用1取代的,看来默认情况下,编译器都会把 const 的变量视为#define一样,直接替换。 那现在的问题就集中在 -O1 到底做了些什么?为什么和不加的时候有区别呢? 还有,-O1 编译 和 与-O1对应的选项 分别注明有什么区别?为什么结论也是不同的……