我认为下面的C程序应输出 1 :
#include <stdio.h>
int main()
{
unsigned int n=18u;
while ((n+17u)>=17u) n-=17u;
printf("%u\n",n+17u);
return 0;
}
但是在VC6,Visual Studio 2010或Visual Studio 2012中编译,都处于发布模式,程序不会输出任何内容而不会退出。
这是VS2012生成的汇编代码:
00BD1000 mov eax,12h
00BD1005 lea eax,[eax-11h]
00BD1008 jmp main+5h (0BD1005h)
似乎编译器做了一些优化并生成了无限循环。
我认为((n+17u)>=17u)
并非总是如此,因为如果n==0xFFFF..FF
,n+17u
将换行到16u
。
我错了,还是编译器错了?
答案 0 :(得分:4)
gcc
和clang
都会编译掉该循环,将其替换为常量1
的printf(使用-O3
。)
我认为你观察到的VC行为是一个错误:无符号算术是明确定义的,你是正确的,溢出应该回绕到小于17的整数。所以gcc
和{{1}做对了。
答案 1 :(得分:1)
MacOS上的gcc和clang:
#include <stdio.h>
int main()
{
unsigned int n=18u;
while ((n+17u)>=17u) {
n-= 17u;
printf("n=%u %u >= %u\n", n, n+17u, 17u);
}
printf("%u\n",n+17u);
return 0;
}
打印
n=1 18 >= 17
n=4294967280 1 >= 17
1
因此n变为“大”并且n的增量使其再次“小”并且循环结束。 我没说太好。
编译器错误很少见,但我认为你找到了一个。恭喜。