I have 8 bool
variables, and I want to "merge" them into a byte.
Is there an easy/preferred method to do this?
How about the other way around, decoding a byte into 8 separate boolean values?
I come in assuming it's not an unreasonable question, but since I couldn't find relevant documentation via Google, it's probably another one of those "nonono all your intuition is wrong" cases.
The cool way (using the multiplication technique)
Of course you may need to make sure that the bool array is correctly 8-byte aligned to avoid performance shoot down and/or UB
How they work?
Suppose we have 8 bools
b[0]
tob[7]
whose least significant bits are named a-h respectively that we want to pack into a single byte. Treating those 8 consecutivebool
s as one 64-bit word and load them we'll get the bits in reversed order in a little-endian machine. Now we'll do a multiplication (here dots are zero bits)The arrows are added so it's easier to see the position of the set bits in the magic number. At this point 8 least significant bits has been put in the top byte, we'll just need to mask the remaining bits out
So the magic number for packing would be
0b1000000001000000001000000001000000001000000001000000001000000001
or0x8040201008040201
. If you're on a big endian machine you'll need to use the magic number0x0102040810204080
which is calculated in a similar mannerFor unpacking we can do a similar multiplication
After multiplying we have the needed bits at the most significant positions, so we need to mask out irrelevant bits and shift the remainings to the least significant positions. The output will be the bytes contain a to h in little endian.
The efficient way
On newer x86 CPUs with BMI2 there are PEXT and PDEP instructions for this purpose. The
pack8bools
function above can be replaced withAnd the
unpack8bools
function can be implemented asThe hard way:
And:
Or the cool way:
Then you can assign to one member of the union and read from another. But note that the order of the bits in
Bits
is implementation defined.You would use the bitwise shift operation and casting to archive it. a function could work like this:
Thanks Christian Rau for the correction s!
I'd like to note that type punning through
union
s is UB in C++ (as rodrigo does in his answer. The safest way to do that ismemcpy()
As others have said, the compiler is smart enough to optimize out
memcpy()
.BTW, this is the way that Boost does type punning.
There is no way to pack 8
bool
variables into one byte. There is a way packing 8 logical true/false states in a single byte using Bitmasking.