Bit Fields
Packing sub-byte fields into a struct — the register-map pattern.
This is the one that actually explains why hardware register documentation always comes with a bit diagram — bit fields are how that diagram becomes a struct.
struct status_reg {
unsigned int enable : 1; /* 1 bit */
unsigned int mode : 2; /* 2 bits */
unsigned int : 1; /* 1 padding bit, unnamed */
unsigned int errcode: 4; /* 4 bits */
};
struct status_reg r;
r.enable = 1;
r.mode = 3;The : n after each member tells the compiler to pack it into exactly n bits instead of a full unsigned int — enable and mode and errcode here all share the same underlying word instead of each taking 4 bytes. It's precisely the same layout a register datasheet describes — "bit 0 is enable, bits 1-2 are mode" — just expressed as C instead of a table.
The catch is that exact bit ordering and padding within the word is implementation-defined — portable across compilers and architectures it is not, which is part of why a lot of real driver code still does manual shifting and masking on a plain integer instead of trusting bit-field layout.
Notes from readers
Comments — via GitHub