6

我认为下面的 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.

我错了,还是编译器错了?

4

2 回答 2

4

gcc并且clang都编译掉那个循环,用常量的 printf 替换它1(使用-O3.)

我认为你观察到的 VC 行为是一个错误:无符号算术是明确定义的,你是对的,溢出应该环绕到小于 17 的整数。所以gccclang做对了。

于 2013-11-10T17:13:40.163 回答
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 的增量使其再次“变小”并且循环结束。我说的不太好。

编译器错误很少见,但我认为您找到了。恭喜。

于 2013-11-10T17:15:35.803 回答