Reputation: 16310
C++ has logical operations, !a
, a && b
, a || b
applicable to true/false values.
And it has bitwise operations, applicable to all (integer?) types, ~a
, a & b
, a | b
, a ^ b
, (a << N
, a >> N
).
Together with in place mutation operators, a &= b
, a |= b
, a ^= b
, (a <<= b
, a >>= b
).
What confuses me is that bitwise operations could be acting on bits of bool
that are not at all part of the true/false value.
Even doing unnecessary bit operations.
I guess that last fact makes bitwise shifting undefined for bool
and that makes me doubt whether all bitwise operations are valid at all.
So, are these equivalent for bool types? ~a == !a
, a && b == a & b
, a || b == a | b
?
For some reason (won't question here) there is no "in-place" logical mutation operators (i.e. a &&= b
, a ||= b
).
This inspires these questions, are these other bitwise operations valid on bools themselves? are a &= b
and a |= b
always equivalent to a = a && b
and a = a || b
respectively?** (no "in-place" xor a = a ^ b
?)
Some examples: https://godbolt.org/z/hcccG8c9o
Upvotes: 2
Views: 305
Reputation: 76859
(For simplicity I will assume C++20, i.e. two's complement representation of integer types. What I am writing may technically not hold prior to C++20 for all theoretically possible conforming representations of integer types.)
What confuses me is that bitwise operations could be acting on bits of bool that are not at all part of the true/false value.
The built-in bitwise operations have the usual arithmetic conversions applied to their operands first. For integral operands that implies integral promotions: Operands with a conversion rank below that of int
are converted to int
first (or unsigned int
or a higher rank integral type if int
can't hold all values of the original type).
The promotion always leaves the original value unchanged. In the case of bool
, true
is mapped to 1
and false
to 0
. So the result after promotion will have its least significant bit either set or unset, while all other bits are unset. Also, there are always at least 15
such bits, because int
must be at least 16 bit wide.
As a consequence ~a == !a
is always false. ~
will set these additional bits, while promotion of !a
will not. However bool(~a) == bool(!a)
is true
only if a
is false
, because with additional bits set bool(~a)
is always true
.
a && b == a & b
is always true, because additional bits will be zero when &
is applied.
a || b == a | b
is always true, because additional bits will again remain zero.
However, if a
and b
are actual expressions, then there is another difference in that the logical operators short-circuit evaluation, while the bitwise ones don't. Therefore, the side effects may be different.
Also, the result of the logical operators will be a bool
, while that of the bitwise ones will be a int
. Therefore they are not interchangeable as they might e.g. affect overload resolution where their result is used.
Also, this applies only for the built-in operators. If any overloaded operators are involved, nothing is guaranteed.
Upvotes: 5