Here is a slightly more elaborate example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | #include <stdio.h> #include <limits.h> unsigned int ratio(unsigned int x, unsigned int y) { if (x <= UINT_MAX / 100) x *= 100; else y /= 100; if (y == 0) y = 1; return x / y; } int main(void) { unsigned int count; for (count = 0x3fffffff; count != 0; ++count) { /* do something */ /* show progress */ printf("\r%u%% done", ratio(count, UINT_MAX)); } return 0; } |
This program goes through the entire range of the unsigned int type, performing some action for each. It shows the progress by calling a function to compute the ratio of count to the maximum possible value. Again, count is incremented in each step, and hence will reach the value zero at some point.
The program works as expected on the compilers I tried, except for cl.exe from VC7 and VC71 with the /O2 switch, which stop at 25%. In case you wondered about the starting point of 0x3fffffff, that’s the reason — no need to watch your machine chew it’s way through all integers up to 25%.
Looking at the code generated for the loop:
1 2 3 4 5 | $L873: ... inc esi add edi, 100 ; 00000064H jne short $L873 |
We see that it fails because the two instructions before the conditional jump have been reversed. Again it looks like the optimizer fails to recognize the importance of the increment to the loop.
Believe it or not this bug also exist on the gcc/g++ compiler. Even without optimizations (I don’t know if you can optimize code on gcc? Can you?)
That is interesting, may I ask which version of gcc you tried and on what platform?
Using MinGW gcc 4.4.0 the program seemed to work here.
gcc has a number of options for optimization, check out http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html
It is still present in Visual C++ 2008 SP1, and from the reply on the Visual C++ forum it appears to also be in the VS 2010 beta.
I have submitted a bug report to Microsoft.
Microsoft responded to the bug report: