how to use or ||

Started by
12 comments, last by Khatharr 9 years, 9 months ago

It should be noted that performing your comparisons using multiple Boolean variables means that you cannot take advantage of short-circuit evaluation.

VS2012, compiled with default release mode settings:


..

Resulting disassembly:


...

Compilers are very, very smart.

They are, hopefully, also very smart not to do that when the evaluations of the temporary variables have side effects because that would change the meaning of the program. Your example works because the individual conditions does not have any observable side effects. If the expressions have side effects, or otherwise relies on short circuiting to prevent the evaluation of an expression in the condition (for example checking for null-pointer before accessing a member of an object), expanding the expressions to temporary variables before the if-statement won't work.

Advertisement

It should be noted that performing your comparisons using multiple Boolean variables means that you cannot take advantage of short-circuit evaluation.

VS2012, compiled with default release mode settings:


..

Resulting disassembly:


...

Compilers are very, very smart.

They are, hopefully, also very smart not to do that when the evaluations of the temporary variables have side effects because that would change the meaning of the program. Your example works because the individual conditions does not have any observable side effects. If the expressions have side effects, or otherwise relies on short circuiting to prevent the evaluation of an expression in the condition (for example checking for null-pointer before accessing a member of an object), expanding the expressions to temporary variables before the if-statement won't work.

OP's code does not include side effects.

On the other hand, in the case that the statements do (or may) have side effects, the compiler will obviously not screw it over.

In that case, though, it's better to just write the test sequence out clearly rather than relying on obscure details of the spec. If you want to do something obvious like null checking, you can just do that into the temp:


bool a = (ptr && ptr->something);
bool b = stuff;
if(a || b) {etc}
void hurrrrrrrr() {__asm sub [ebp+4],5;}

There are ten kinds of people in this world: those who understand binary and those who don't.


Compilers are very, very smart.

But they don't perform magic. I'm specifically referring to cases such as this:

#include <iostream>

bool SomeExpensiveComputation()
{
    std::cout << "D'oh!" << std::endl;
    return true;
}

int main()
{
    int value = 42;
   
    if ( value > 0 || SomeExpensiveComputation() )
    {
        std::cout << "Example 1" << std::endl;
    }
   
    bool b1 = value > 0;
    bool b2 = SomeExpensiveComputation();
   
    if ( b1 || b2 )
    {
        std::cout << "Example 2" << std::endl;
    }
}

http://coliru.stacked-crooked.com/a/339dc09bdbc542dc

That's just begging for a long debug session some time in the distant future. Stuff like that is hard to spot if you aren't looking for it.


bool execute = false;
if(value > 0) {execute = true;}
else if(SomeExpensiveComputation()) {execute = true;}
if(execute) {std::cout << "Example 1" << std::endl;}

^ Compiles the same, but is far more clear about what's going on.

Alternatively, it may be a good idea to at least leave a comment indicating that you're making use of a short circuit.

void hurrrrrrrr() {__asm sub [ebp+4],5;}

There are ten kinds of people in this world: those who understand binary and those who don't.

This topic is closed to new replies.

Advertisement