The standard (9.6 from the working draft ) says the following:
indicates a bit field; its length begins with the name of the bit field of the colon. The bitfield attribute is not part of the class member type. A constant expression must be an integral constant expression with a value greater than or equal to zero. a constant expression may be greater than the number of bits in the representation of an object (3.9) such as bit fields; in such cases, additional bits are used as complement bits and do not participate in the representation of the values (3.9) of the bit field. The distribution of bit fields within a class object is determined by the implementation. Alignment of bit fields from implementation . Bit fields are packed into some addressable distribution unit. [Note. Distribution blocks of bit field blocks on some machines, not others. Bit fields are assigned from right to left on some machines, from left to right on others. -end note]
(my emphasis)
So this will depend on your compiler. What apparently happens in your case - and I would call it pretty normal behavior, is that it only combines bit fields of the same type and then packs the structure into a 4 byte boundary, so in the first case, we we have:
struct a { uint32_t foreColor_ : 32; // 4 bytes (total) uint32_t backColor_ : 32; // 8 bytes uint16_t lfHeight_ : 16; // 10 bytes uint16_t flags_: 4; // 12 bytes bool lfBold_: 1; // 13 bytes bool lfItalic_: 1; bool lfUnderLine_: 1; bool lfDashLine_: 1; bool lfStrike_: 1; bool lfSubscript_: 1; bool lfSuperscript_: 1; // still 13 bytes };
which is then padded with 16 bytes, and in the second -
struct a { uint32_t foreColor_ : 32; // 4 bytes (total) uint32_t backColor_ : 32; // 8 bytes uint16_t lfHeight_ : 16; // 10 bytes uint8_t flags_: 4; // 11 bytes bool lfBold_: 1; // 12 bytes bool lfItalic_: 1; bool lfUnderLine_: 1; bool lfDashLine_: 1; bool lfStrike_: 1; bool lfSubscript_: 1; bool lfSuperscript_: 1; // still 12 bytes };
Who does not need to fill in and remains at 12 bytes.
source share