【发布时间】:2015-09-28 14:47:25
【问题描述】:
我发现以下未经优化和-Os优化编译的代码的汇编结果之间的差异非常奇怪。
#include <stdio.h>
int main(){
int i;
for(i=3;i>2;i++);
printf("%d\n",i);
return 0;
}
未经优化的代码结果:
000000000040052d <main>:
40052d: 55 push %rbp
40052e: 48 89 e5 mov %rsp,%rbp
400531: 48 83 ec 10 sub $0x10,%rsp
400535: c7 45 fc 03 00 00 00 movl $0x3,-0x4(%rbp)
40053c: c7 45 fc 03 00 00 00 movl $0x3,-0x4(%rbp)
400543: eb 04 jmp 400549 <main+0x1c>
400545: 83 45 fc 01 addl $0x1,-0x4(%rbp)
400549: 83 7d fc 02 cmpl $0x2,-0x4(%rbp)
40054d: 7f f6 jg 400545 <main+0x18>
40054f: 8b 45 fc mov -0x4(%rbp),%eax
400552: 89 c6 mov %eax,%esi
400554: bf f4 05 40 00 mov $0x4005f4,%edi
400559: b8 00 00 00 00 mov $0x0,%eax
40055e: e8 ad fe ff ff callq 400410 <printf@plt>
400563: b8 00 00 00 00 mov $0x0,%eax
400568: c9 leaveq
400569: c3 retq
输出是:-2147483648(正如我在 PC 上所期望的那样)
加上-Os的代码结果:
0000000000400400 <main>:
400400: eb fe jmp 400400 <main>
我认为第二个结果是错误的!!!我认为编译器应该已经编译了与代码相对应的东西:
printf("%d\n",-2147483648);
【问题讨论】:
-
不,不是。检查未定义的行为是没有用的。你的
for循环最终会溢出一个有符号整数 -> UB! -
该行为仅针对 unsigned 定义
-
@SergioFormiggini:“但我想要!”。 我的想法是,如果你不能接受 C 是什么,你应该坚持使用 Python 或其他东西。
-
未定义的行为意味着任何事情都可能发生。绝对任何事情,包括每次产生不同的结果。或者根本没有结果。
-
gcc 有选项
-ftrapv使签名溢出崩溃和-fwrapv使其环绕。