I was messing around a bit in C++ when I came across an issue that made absolutely no sense to me. For some reason with a variable equal to 2, 2 > 0 returns false, but 2 <= 0 and 2 >= 0 return true, while also somehow 2 < 0 and 2 == 0 return false. However, if I use just a static 2, everything works as intended.
Here’s the entire code:
#include <iostream>
using namespace std;
long long f (long long n)
{
while (n > 0);
{
n /= 10;
}
cout << n << ": " << endl;
cout << n << " > 0 = " << (n > 0) << endl;
cout << n << " < 0 = " << (n < 0) << endl;
cout << n << " >= 0 = " << (n >= 0) << endl;
cout << n << " <= 0 = " << (n <= 0) << endl;
cout << 2 << ": " << endl;
cout << 2 << " > 0 = " << (2 > 0) << endl;
cout << 2 << " < 0 = " << (2 < 0) << endl;
cout << 2 << " >= 0 = " << (2 >= 0) << endl;
cout << 2 << " <= 0 = " << (2 <= 0) << endl;
return 0;
}
int main()
{
long long n = 27;
f(n);
}
This returns:
2:
2 > 0 = 0
2 < 0 = 0
2 >= 0 = 1
2 <= 0 = 1
2:
2 > 0 = 1
2 < 0 = 0
2 >= 0 = 1
2 <= 0 = 0
>Solution :
The compiler assumes that n is a zero when evaluating the conditionals.
It’s allowed to do that since while (n > 0); is undefined for positive n, and a compiler is allowed to assume there is no undefined behaviour.
This is plausible since conditionals can cause branch prediction failures whereas simple output of n (which is 2 once you’ve taken the integer division by 10) does not. A lot of compiler optimisation these days is centred around not dumping the pipeline.
With something like this, check the generated assembly.
With a less aggressively optimising compiler, you would probably end up with an infinite loop with no output.