Возможно ли и правильно ли сформировать объединение из битового поля в C?

У меня есть следующий союз, и он работает правильно:

#pragma pack(1)
...
union
{
    uint8_t opcode;
    struct
    {
        uint8_t z : 3;
        uint8_t y : 3;
        uint8_t x : 2;
    };
}opcode;    

Размер объединения ровно один байт, согласно

printf ("%zu\n", sizeof opcode);  

Проблема возникает, когда я пытаюсь сделать объединение из битового поля:

union
{
    uint8_t opcode;
    struct
    {
        uint8_t z : 3;
        union
        {
            uint8_t y : 3;
            struct
            {
                uint8_t p : 2;
                uint8_t q : 1;
            };
        }y;
        uint8_t x : 2;
    };
}opcode;    

Результат

printf ("%zu\n", sizeof opcode);  

составляет 3 байта. Конечно, я могу обойти это с помощью макросов, но возможно ли это вообще?


person pugnator    schedule 20.03.2014    source источник


Ответы (2)


Нет, невозможно иметь структуры размером в доли байта.

Обоснование:

Должна быть возможность сделать указатель на структуру, а наименьшая адресуемая единица — 1 байт.

Примечание. Это ограничение существует во всех известных мне компиляторах. Я не знаю, действительно ли это предусмотрено стандартом C.

person Klas Lindbäck    schedule 20.03.2014

В вашем коде будет объявлена ​​3-байтовая структура данных, потому что, как уже указал Клас, структура всегда дополняется до наименьшей адресуемой единицы.

Но можно делать то, что вы хотите, встраивая несколько структур верхнего уровня в объединение и добавляя отступы, когда это необходимо:

union {
    uint8_t opcode;
    struct {
        uint8_t z:3;
        uint8_t y:3;
        uint8_t x:2;
    };
    struct {
        uint8_t:3;
        uint8_t p:2;
        uint8_t q:1;
    };
} opcode;

Обратите внимание, что можно объявлять битовые поля без имени для заполнения. Это стандартная функция языка C.

person CliffordVienna    schedule 20.03.2014
comment
Отлично! Очень элегантное решение. Большое спасибо! - person pugnator; 20.03.2014