>>1
Generally, is storing and retrieving minor states using bitwise operations better or worse than using separate boolean values for each state?
Depends. Checking if a bit (or bit mask) is set or unset is no more or less performant than checking whole integers/booleans.
If you need to conditionally set/clear a bitmask without branching, it takes an additional three operations, whereas with whole integers modern CPUs have conditional move instructions which don't branch. Branch-less code is often faster code.
int bit_fields = <some value>; // our set of bits
int bit_mask = 0x8001; // mask to set
bool condition = <some value>;
// conditionally set/clear the bits specified in bit_mask in bit_fields WITHOUT branching
bit_fields = (bit_fields & ~bit_mask) | (-condition & bit_mask);
// conditionally set/clear the bits specified in bit_mask in bit_fields WITH branching
if (condition)
bit_fields |= bit_mask;
else
bit_fields &= ~bit_mask;
If you were just using whole integers, it would optimize down to something like:
Bit packing can of course lower the memory footprint of your code, making your data structures fit within the cache line size of your target CPU (usually between 32 and 128 bytes on consumer desktop/mobile processors) and thus resulting in less cache misses and CPU stalls.
do people even use this technique in serious applications?
Yes. Operating system, device driver, systems applications, and game developers use it. Anyone interested in writing efficient, unbloated code.