Question

I think the C program below shall output 1:

#include <stdio.h>
int main()
{
    unsigned int n=18u;
    while ((n+17u)>=17u) n-=17u;
    printf("%u\n",n+17u);
    return 0;
}

But compiled in VC6, Visual Studio 2010, or Visual Studio 2012, all in release mode, the program doesn't output anything and doesn't quit.

This is the assembly code generated by VS2012:

00BD1000  mov         eax,12h
00BD1005  lea         eax,[eax-11h]
00BD1008  jmp         main+5h (0BD1005h)

It seems that the compiler did some optimization and generated an infinite loop.

I think that ((n+17u)>=17u) is not always true, because if n==0xFFFF..FF, n+17u would wrap to 16u.

Am I wrong, or are the compilers wrong?

Was it helpful?

Solution

gcc and clang both compile away that loop, replacing it with a printf of the constant 1 (using -O3.)

I think the VC behaviour you observe is a bug: unsigned arithmetic is well-defined, and you're right that the overflow should wrap around to an integer less than 17. So gcc and clang get it right.

OTHER TIPS

gcc and clang on MacOS:

#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;
}

prints

n=1 18 >= 17
n=4294967280 1 >= 17
1

So n goes "big" and the increment to n makes it "small" again and the loop ends. I didn't say that too well.

Compiler bugs are rare but I think you found one. Congratulations.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top