Using Bitwise Operators for Booleans in C++

Using bitwise operators for Booleans in C++

|| and && are boolean operators and the built-in ones are guaranteed to return either true or false. Nothing else.

|, & and ^ are bitwise operators. When the domain of numbers you operate on is just 1 and 0, then they are exactly the same, but in cases where your booleans are not strictly 1 and 0 – as is the case with the C language – you may end up with some behavior you didn't want. For instance:

BOOL two = 2;
BOOL one = 1;
BOOL and = two & one; //and = 0
BOOL cand = two && one; //cand = 1

In C++, however, the bool type is guaranteed to be only either a true or a false (which convert implicitly to respectively 1 and 0), so it's less of a worry from this stance, but the fact that people aren't used to seeing such things in code makes a good argument for not doing it. Just say b = b && x and be done with it.

Using bitwise & on boolean

You just shouldn't use a bitwise operator on Boolean values. Apparently the compiler promotes the output of funcReturningBool or the variable flag to a signed integer, and warns you of possible unexpected effects.

You should stick to Boolean operators. Had &&= existed, you could have written flag &&= funcReturningBool();. Instead, use flag = flag && funcReturningBool();

Boolean bitwise and logical operators

As noted in the comments, you should use logical operators when you're doing logic and bitwise operators when doing bitwise operations.

One of the main differences among these is that C++ will short-circuit the logical operations; meaning that it will stop evaluating the operands as soon as it's clear what the result of the operation is.

As an example, this code:

bool foo() {
std::puts("foo");
return true;
}

bool bar() {
std::puts("bar");
return true;
}

//...

auto const res = foo() || bar();

will only output:

foo

Function bar won't be evaluated as, in this case, evaluating foo is enough to know the result of expression foo() || bar() is true.

Absolute value abs(x) using bitwise operators and Boolean logic

Assuming 32-bit words, as stated in the question:

For negative x, x >> 31 is implementation-defined in the C and C++ standards. The author of the code expects two’s complement integers and an arithmetic right-shift, in which x >> 31 produces all zero bits if the sign bit of x is zero and all one bits if the sign bit is one.

Thus, if x is positive or zero, y is zero, and x + y is x, so (x + y) ^ y is x, which is the absolute value of x.

If x is negative, y is all ones, which represents −1 in two’s complement. Then x + y is x - 1. Then XORing with all ones inverts all the bits. Inverting all the bits is equivalent to taking the two’s complement and subtracting one, and two’s complement is the method used to negate integers in two’s complement format. In other words, XORing q with all ones gives -q - 1. So x - 1 XORed with all ones produces -(x - 1) - 1 = -x + 1 - 1 = -x, which is the absolute value of x except when x is the minimum possible value for the format (−2,147,483,648 for 32-bit two’s complement), in which case the absolute value (2,147,483,648) is too large to represent, and the resulting bit pattern is just the original x.

Can you bitwise shift a bool in C++?

From Shift operators [expr.shift]

The operands shall be of integral or unscoped enumeration type and integral promotions are performed.
The type of the result is that of the promoted left operand

bool is an integral type so the code is well formed (bool is promoted to int and result is an int).

From [conv.prom], we show what integers the booleans get promoted to:

A prvalue of type bool can be converted to a prvalue of type int, with false becoming zero and true becoming one

Afterwards, the shift behaves normally. (Thanks, @chris)

Can I use bitwise operators instead of logical ones?

One possible answer is: optimization. For example:

if ((age < 0) | (age > 100))

Let assume that age = -5, no need to evaluate (age > 100) since the first condition is satisfied (-5<0). However, the previous code will do evaluate the (age > 100) expression which is not necessary.

With:

if ((age < 0) || (age > 100))

Only the first part will be evaluated.

Note: As @Lundin mentioned in the comments, sometimes | is faster than || due to the accuracy of branching for the second option (and the problem of mis-prediction). So in cases where the other expression is so inexpensive, the | option may be faster. So the only way to know in those cases is to benchmark the code on the target platform.


The most important answer is to avoid undefined behaviors and errors:

You may imagine this code:

int* int_ptr = nullptr;
if ((int_ptr != nullptr) & (*int_ptr == 5))

This code contains undefined behaviour. However, if you replace the & with &&, No undefined behaviour exists anymore.

Understanding bitwise XOR (^) with boolean variables

As bool is a narrower type than an int, both arguments are implicitly converted to an int prior to the XOR being evaluated. true assumes the value 1, and false assumes the value 0.

If that result is non-zero then the if body runs, and that happens if and only if body1awake is not equal to body2awake.

So perhaps the equivalent

if (body1awake != body2awake)

would have been better. If the author thinks their way is faster then they need a stern talking to with compiler optimisations and as-if rule being introduced into the conversation.



Related Topics



Leave a reply



Submit