Будет ли это битовое поле работать так, как я ожидаю?
Я немного читал о битовых полях в C, о том, как стандарт C не обеспечивает какой-либо конкретный порядок полей в машинном слове, и так далее.
Я надеюсь, что этот вопрос соответствует формату SO.
Мой вопрос заключается в том, будет ли моя структура (определение следующее) действительно работать так, как я ожидаю. Вот определение, которое я придумал, а затем я буду обсуждать, что я хочу:
typedef enum {
STATE_ONE,
STATE_TWO,
STATE_THREE,
STATE_FOUR
} __attribute__ ((packed)) State;
typedef struct MyStruct {
// One of State enum (maximum of 4 states).
unsigned state : 2;
// Remaining 30 bits are used differently depending on 'state'.
union {
// If 'state' is STATE_ONE (0), the remaining bits are an ID number.
unsigned id : 30;
/*
* For all other states, the remaining bits are the 2-tuple:
* (buffer A index, buffer B index).
*/
struct {
unsigned bufferAIdx : 16;
unsigned bufferBIdx : 14;
} __attribute__ ((packed)) index;
} __attribute__ ((packed));
} __attribute__ ((packed)) MyStruct;
(Это для GCC, таким образом, __attribute__
директивы).
Вы, вероятно, можете сказать, для чего я: в зависимости от значения поля 'state', я хочу использовать оставшиеся 30 бит для разных целей. Это должен быть либо идентификационный номер, либо два набора индексов в различных буферах. И каждый экземпляр MyStruct должен умещаться максимум в 5 байтах.
Так что я хочу иметь возможность сделать что-то на этот счет:
MyStruct a, b;
a.state = STATE_ONE;
a.id = 123456;
b.state = STATE_THREE;
b.index.bufferAIdx = 6;
b.index.bufferBIdx = 2;
В основном я ищу информацию о том, "правильно ли это делать". Другими словами, я неправильно использую идеи битовых полей / союзов здесь? Если вы собираетесь поддерживать этот код, будете ли вы в ужасе, увидев это? Или вы предпочитаете видеть весь объект данных, хранящийся в uint32_t
типа и манипулируют с помощью маскировки и сдвига?
1 ответ
Как начало любого union
или же struct
будет выровнен по границе, таким образом вы не сможете уместить все ваши данные в 32 бита. Вы должны заключить в капсулу свой union
а также struct
наоборот, атрибуты удалены для удобства чтения:
typedef struct MyStruct {
union {
struct {
unsigned state : 2;
unsigned id : 30;
}
struct {
unsigned /* unused */ : 2;
unsigned bufferAIdx : 16;
unsigned bufferBIdx : 14;
};
};
};