7

Why does the sizes of these two structs differ?

#pragma pack(push, 1)
    struct WordA
    {
        uint32_t address           : 8;
        uint32_t data             : 20;
        uint32_t sign              : 1;
        uint32_t stateMatrix : 2;
        uint32_t parity            : 1;
    };

    struct WordB
    {
        uint8_t address;
        uint32_t data             : 20;
        uint8_t sign              : 1;
        uint8_t stateMatrix : 2;
        uint8_t parity            : 1;
    };
#pragma pack(pop)

Somehow WordB occupies 6 bytes instead of four, while WordA occupies exactly 32 bits. I assumed that given the sum of used bits inside a struct would yield both structs to be of the same size. Apparently I am wrong, but I cannot find an explanation why. Bit fields page shows only examples when all of the struct members are of the same type, which is a case of WordA.

Can anybody explain, why the sizes don't match and if it is according to the standard or implementation-defined?

Sergey Kolesnik
  • 3,009
  • 1
  • 8
  • 28
  • 1
    bitfield is implementation specific, but generally, bitfield doesn't split between different underlying types. – Jarod42 Dec 07 '20 at 11:07
  • @Jarod42 `bitfield doesn't split between different underlying types.` I figured that might be the reason, but I would like to have some reference to the standard. – Sergey Kolesnik Dec 07 '20 at 11:12
  • @Jarod42 I've renamed the question to be specific. – Sergey Kolesnik Dec 07 '20 at 11:14
  • How should the compiler see that its allowed to join `address` which is not a bitfield with the rest of the bitfields? – Surt Dec 07 '20 at 11:31

1 Answers1

4

Why can't a bit field be split between different underlying types?

It can in the sense that standard allows it.

It wasn't because that's what the language implementer (or rather, the designer of the ABI) chose. This decision may have been preferred because it may make the program faster or the compiler easier to implement.

Here is the standard quote:

[class.bit]

... Allocation of bit-fields within a class object is implementation-defined. Alignment of bit-fields is implementation-defined. Bit-fields are packed into some addressable allocation unit.

eerorika
  • 232,697
  • 12
  • 197
  • 326
  • Could you please refer to the standard? I will accept your answer in that case. – Sergey Kolesnik Dec 07 '20 at 11:31
  • @SergeyKolesnik Added quote. – eerorika Dec 07 '20 at 11:33
  • 1
    I think that standard quote proves the opposite. The bits field have to be packed into their **own** addressable unit, e.g. a `uint32_t` which does not overlap the non-bitfield `uint8_t address;` – MSalters Dec 07 '20 at 12:59
  • @MSalters it will not overlap it even if it was a bitfield. – Sergey Kolesnik Dec 09 '20 at 06:01
  • @SergeyKolesnik: If they were all bitfields, the bits themselves would not overlap, but the bitfields would be allocated from the same addressable unit. But in `WordB` only 24 of the `uint32_t` bits are used, so there are 8 unused bits. – MSalters Dec 10 '20 at 08:07