Dab*_*abo 6 c assembly for-loop
我正在运行一些测试,看看++ i和i ++是如何转换为asm的.我写了一个简单的:
int main()
{
int i;
for(i=0;i<1000000;++i);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
使用gcc test.c -O0 -o test编译它,并使用objdump -d test检查asm :
4004ed: 48 89 e5 mov %rsp,%rbp
4004f0: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp) // i=0;
4004f7: eb 04 jmp 4004fd <main+0x11>
4004f9: 83 45 fc 01 addl $0x1,-0x4(%rbp) // ++i;
4004fd: 81 7d fc 3f 42 0f 00 cmpl $0xf423f,-0x4(%rbp) //
400504: 7e f3 jle 4004f9 <main+0xd> //i<1000000;
400506: b8 00 00 00 00 mov $0x0,%eax
40050b: 5d pop %rbp
40050c: c3 retq
Run Code Online (Sandbox Code Playgroud)
到现在为止还挺好.奇怪的事情(如果我理解asm代码正确)是当我<1000000而不是我写了<10000000000.对于具有停止条件的循环完全相同i <10000000000转换为以下汇编代码:
4004ed: 48 89 e5 mov %rsp,%rbp
4004f0: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp)
4004f7: 83 45 fc 01 addl $0x1,-0x4(%rbp)
4004fb: eb fa jmp 4004f7 <main+0xb>
Run Code Online (Sandbox Code Playgroud)
根据我的理解,这是无限循环,导致完全相同的asm生成:
for(i=0;;++i);
Run Code Online (Sandbox Code Playgroud)
问题是,它是否真的可能被编译为无限循环?为什么?我正在使用Ubuntu 13.04,x86_64.
谢谢.
Nik*_* C. 17
发生这种情况是因为int
架构上的最大值永远不会达到10000000000.它会在达到该值之前的某个时刻溢出.因此,条件i < 10000000000
将始终评估为真,这意味着这是一个无限循环.
编译器能够在编译时扣除这个,这就是它为无限循环生成适当的程序集的原因.
编译器能够就此发出警告.为此,您可以启用"额外"警告级别:
gcc -Wextra
例如GCC 4.8.2会告诉你:
warning: comparison is always true due to limited range of data type [-Wtype-limits]
for (i = 0; i < 10000000000; ++i);
^
Run Code Online (Sandbox Code Playgroud)
它甚至会告诉您确切控制此类警告的特定警告选项(Wtype-limits).
整数范围是:-2,147,483,648到2,147,483,647
你就像在它之上.