Почему sizeof битового поля в 64 бита равен 12, а не 8?

Неожиданный для меня поворот:

struct frame_head
{
    unsigned size   : 24;
    unsigned height : 12;
    unsigned width  : 12;
    unsigned pts    : 15;
    bool key        :  1;
};
printf("%d\n", sizeof(frame_head)); // 12... Но почему не 8???

Зачем GNU g++ надо ещё 4 байта, если там всего заказано 64 бита / 8 байт?


Ответы (2 шт):

Автор решения: Alexey Nikolaev

Потому что упаковка работает так:

struct frame_head
{
    unsigned size   : 24;   // под это поле зарезервируется слово (32-бита) потому что следующее поле не влезает в слово
    ////////////////////
    unsigned height : 12;
    unsigned width  : 12;   // под эти 2 поля зарезервируется слово (32-бита) потому что следующее поле не влезает в слово
    ////////////////////
    unsigned pts    : 15;
    bool key        :  1;   // под эти 2 поля зарезервируется слово (32-бита)
};

ответ к первому комментарию:

struct frame_head
{
    unsigned size   : 20;
    unsigned height : 12;   // под эти 2 поля зарезервируется слово (32-бита) потому что следующее поле не влезает в слово
    ////////////////////
    unsigned width  : 12;   
    unsigned pts    : 15;
    bool key        :  1;   // под эти 3 поля зарезервируется слово (32-бита)
};
→ Ссылка
Автор решения: Swift

Скажите компилятору что все поля упаковываются в 64-битную ячейку памяти - memory location, и если вся последовательность полей с ненулевой длиной помещается в таковое, они ее займут. Поле height не помещается в unsigned -32 битное слово и занимает новое слово. Лучше использовать типы с гарантированным размером - uint64_t и пр.

→ Ссылка