Reputation: 1721
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
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
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