Anthony Raimondo
Anthony Raimondo

Reputation: 1721

Efficiency of logical "or" on bool values in C++

bool x = false, y = false, z = true;

if(x || y || z){}

or

if(x | y | z){}

Does the second if statement perform a bit wise "or" operation on all booleans? treating them as if there were bytes? ex) (0000 | 0000 | 0001) = true...

Or does it act like a Java | on booleans, where it will evaluate every bool in the expression even if the first was true?

I want to know how bit wise operators work on bool values. is it equivalent to integer bitwise operations?

Upvotes: 3

Views: 2713

Answers (2)

dwarduk
dwarduk

Reputation: 959

The second acts a java | on integers, a bit-wise or. As C originally didn't have a boolean type, the if statement reads any non-zero as true, so you can use it as that, but it is often more efficient to use the short-circuiting operator || instead, especially when calling functions that return the conditions.

I would also like to point out that short-circuit lets you check unsafe conditions, like if(myptr == NULL || myptr->struct_member < 0) return -1;, while using the bitwise or there will give you a segfault when myptr is null.

Upvotes: 3

A. H.
A. H.

Reputation: 952

Efficiency depends, the logical or operator || is a short circuit operator meaning if x in your example is true it will not evaluate y or z. If it was a logical and && then if x is false, it will not test y or z. Its important to note that this operation does not exist as an instruction so that means you have to use test and jump instructions. This means branching, which slows down things. Since modern CPU's are pipelined.

But the real answer is it depends, like many other questions of this nature, as sometimes the benefit of short circuiting operations outweighs the cost.

In the following extremely simple example you can see that bitwise or | is superior.

#include <iostream>


bool test1(bool a, bool b, bool c)
{
    return a | b | c;
}

bool test2(bool a, bool b, bool c)
{
    return a || b || c;
}

int main()
{
  bool a = true;
  bool b = false;
  bool c = true;
  test1(a,b,c);
  test2(a,b,c);
  return 0;
}

The following is the intel-style assembly listings produced by gcc-4.8 with -O3 :
test1 assembly :

_Z5test1bbb:
.LFB1264:
    .cfi_startproc
    mov eax, edx
    or  eax, esi
    or  eax, edi
    ret
    .cfi_endproc

test2 assembly :

_Z5test2bbb:
.LFB1265:
    .cfi_startproc
    test    dil, dil
    jne .L6
    test    sil, sil
    mov eax, edx
    jne .L6
    rep; ret
    .p2align 4,,10
    .p2align 3
.L6:
    mov eax, 1
    ret
    .cfi_endproc

You can see that it has branch instructions, which mess up the pipeline.

Sometimes however short-circuiting is worth it such as

return x && deep_recursion_function();

Disclaimer:

I would always use logical operators on bools. Unless performance really is critical, or maybe simple case like in test1 and test2 but with lots of bools. And in either case first verify that you do get an improvement.

Upvotes: 8

Related Questions