for(i = 0; i <10000000000; ++ i)编译成无限循环?

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).


Jon*_*cht 5

整数范围是:-2,147,483,648到2,147,483,647

你就像在它之上.

  • `int`范围可能更小或更大.根据C11§5.2.4.2.1,_minimum_范围是-32767到+32767.这种16位范围-32768到+32767在2014年通常在嵌入式处理器中找到. (2认同)