(aka "Structured Bitfields", "Named Register Bits")
In high performance applications such as embedded systems, drivers, game engines, protocol parsers, bit masking becomes a solution to put more information in less space. It's also becomes necessary for modifying hardware mapped registers.
Doing this is often dirty and error prone. We've all been there using OR's with bit shifts, it's dumb. It ends up like this:
reg |= (1u << 4); // turn on party mode
reg &= ~(1u << 3); // turn off high brightness
if (reg & (1u << 7)) { ... } // check factory test modeIt's error-prone, hard to read, easy to mess up bit positions during refactors, and terrible for code review. There's a much cleaner, self-documenting way that has been in the C language since forever:
union {
uint8_t raw;
struct {
uint8_t idle : 1; // [0]
uint8_t low_brightness : 1; // [1]
uint8_t normal_brightness : 1; // [2]
uint8_t high_brightness : 1; // [3]
uint8_t party_mode : 1; // [4]
uint8_t debug_mode : 1; // [5]
uint8_t reserved : 1; // [6]
uint8_t factory_test : 1; // [7] MSB
} bits;
} status_reg;
status_reg.bits.party_mode = 1; // readable!
status_reg.bits.high_brightness = 0;Take a look at bitPacking.c, compile it with the following command and play around with it. It works awesome and is a better methond then old school Bit Masking.
gcc bitPacking.c -o rumMe
./runMeA senior engineer on my team showed me this trick. I was super impressed and thought all of you should know about it too.
It's made our code base super clean and stable.