Why is 2 not > 0 ?? It is instead <= 0, but not < 0, nor == 0

Viewed 111

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
2 Answers

Dumb mistake, left the semicolon after the while(n > 0) and seems that caused some weird side effects.

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 outputting 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.

Related