I'm working with Visual Studio 2012 on a Windows 7 machine and when trying to run the following code snippet (compiled with the default VC11 C++ compiler in x64 mode) the assertion fails, which means, that the inner loop is never entered:
void loopTest1()
{
const unsigned int k = 1;
for (int m=0; m<3; ++m)
{
int acc = 0;
for (int n=m-k; n<=m+k; ++n)
{
if (n<0 || n>=3) continue;
++acc;
}
assert (acc>0);
cout << "acc: " << acc << endl;
}
}
Now I change the inner loop's end condition:
void loopTest2()
{
const unsigned int k = 1;
for (int m=0; m<3; ++m)
{
int acc = 0;
int l = m+k; // this line was added
for (int n=m-k; n<=l; ++n) // m+k was replaced by l
{
if (n<0 || n>=3) continue;
++acc;
}
assert (acc>0);
cout << "acc: " << acc << endl;
}
}
Then I get the correct result:
acc: 2
acc: 3
acc: 2
When I replace the const unsigned int k
by a hard-coded 1, it works, too:
void loopTest3()
{
//const unsigned int k = 1;
for (int m=0; m<3; ++m)
{
int acc = 0;
for (int n=m-1; n<=m+1; ++n) //replaced k with 1
{
if (n<0 || n>=3) continue;
++acc;
}
assert (acc>0);
cout << "acc: " << acc << endl;
}
}
Does the compiler perform some false optimizations? Or is there any specific reason, why the behavior in the first case is at least unexpected?
Your int m
is going to be promoted to an unsigned int
. On the first loop, that means m-k
is equal to -1 as an unsigned value, which is the maximum unsigned value and obviously greater than m+k
(when n
is compared, it gets promoted). To put it in perspective, you'll end up with n
being an unsigned representation of -1 and m+k
being 1. Of course when you store that -1 unsigned into a signed integer, it overflows and is technically undefined behaviour. It's most likely keeping its -1 representation and then being promoted back to a max unsigned value.
Here's a summary of sorts of the first iteration:
Iteration 1:
m: 0
k: 1u
n=m-k: -1u = max uint, stored into signed int
m+k: 1u
n<=m+k --> max uint <= 1u
In your second example, n
is not promoted when compared to the other signed integer and it compares two signed integers. In your third, nothing is unsigned.