Ross Rogers
Ross Rogers

Reputation: 24250

Does gcc or other compilers auto convert bitwise or's to boolean or's when used in conditional expressions?

If I have a C statement with the logical OR operator || :

if (isFoo() || isBar())
    blah();

I know the compiler generated code will not execute isBar() if isFoo() returns true.

What about the bitwise OR operator | ?

if (isFoo() | isBar())
    blah();

Likely this is sloppy writing, or if the writer requires isBar() and isFoo() to be both be executed because of those functions' side-effects, then they should express their intent more clearly. Or maybe I'm wrong and this is an acceptable C/C++ idiom.

Nevertheless, will a decent compiler actually generate a temporary variable to do the bitwise or'ing of the return values of isFoo() and isBar() when optimizations are turned on? Or will it instead convert the bitwise OR operation into a logical OR operation in order to allow short-circuit'ing of the boolean expression in order to prevent the calling of isBar()?

Upvotes: 3

Views: 368

Answers (4)

doron
doron

Reputation: 28932

We are talking straight C here so we must have something like

typedef int BOOL;
BOOL isFoo();
BOOL isBAr();

This is because ony C++ (and not C) has a boolean type.

Now when we evaluate isFoo() || isBar() the compiler knows that since we are using logical or if isFoo() returns true, the the whole statement will evaluate to true regardless of the value of isBar(), the compiler can therefore safely short circuit `isBar().

However when we evaluate isFoo() | isBar() we are effectively ORing two integers. The compiler has no way of knowing that isFoo() and isBar() can only return 0 or 1 and therefore will have to evaluate both expressions because even if isFoo() returns 1, the final result may be something different (like 3).

C++ does have a bool type and if isFoo() and isBar() return bools the compiler really does not have to evalueate isBar(). I am not an expert on the C++ specification but I imagine since bitwise operators do not make sense for bool types, the bools will be promoted to int and evaluated accordingly.

Upvotes: 0

Keith Thompson
Keith Thompson

Reputation: 263577

No, this is not a reasonable coding practice. Apart from ||'s short-circuit and ordering semantics, it performs a different operation than |.

|| yields 1 if either operand is non-zero, 0 if both are zero.

| yields the bitwise or of its operands.

As it happens, the truth value of the result is going to be the same (I realized this as I was typing this answer). But consider the corresponding && vs. & operators. This:

if (isFoo() && isBar())

will be true if and only if both functions return a non-zero value, but this:

if (isFoo() & isBar())

will be true if and only if the bitwise and of the results is non-zero. If isFoo() returns 1 and isBar() returns 2 (both true results), then isFoo & isBar() will be 0, or false.

Note that the is*() functions declared in <ctype.h> are only specified to return non-zero for true; they can and do return values other than 0 or 1.

If you really want to avoid the short-circuit behavior of ||, assign the results to temporaries:

bool is_foo = isFoo();
bool is_bar = isBar();
if (is_foo && is_bar) ...

Upvotes: 3

R.. GitHub STOP HELPING ICE
R.. GitHub STOP HELPING ICE

Reputation: 215507

The compiler is free to optimize the "or'ing" however it wants, but the program must behave as if both function calls actually happen, and they could happen in either order. This actually bit me once when I naively changed a || to | because I needed both calls to happen, but forgot that the right-hand call could happen before the left-hand one and that the right-hand one depended on the results of the left-hand one...and the bug didn't show up until somebody decided to try compiling my code with pcc instead of gcc. So my advice is to be careful with stuff like this and write out what you mean clearly.

Finally, note that I said "as if both function calls actually happen", because in the case where the compiler can determine that a function has no side effects, it might optimize out the right-hand side if the left-hand side resulted in a nonzero value.

Upvotes: 9

Benjamin Lindley
Benjamin Lindley

Reputation: 103741

"Nevertheless, will a decent compiler actually generate a temporary variable to do the bitwise or'ing of the return values of isFoo() and isBar() when optimizations are turned on?"

Yes. Short circuiting does not apply to bitwise operators.

Upvotes: 3

Related Questions