Struct Bit Packing и неоднозначность LSB / MSB C++
Мне пришлось написать код C++ для следующего заголовка пакета:
Исходная ссылка на изображение, PNG-версия вышеупомянутого JPEG.
Вот структурный код, который я написал для вышеуказанного формата пакета. Я хочу знать, правильны ли битовые поля uint8_t или uint16_t
struct TelemetryTransferFramePrimaryHeader
{
//-- 6 Ocets Long --//
//-- Master Channel ID (2 octets)--//
uint16_t TransferFrameVersionNumber : 2;
uint16_t SpacecraftID : 10;
uint16_t VirtualChannelID : 3;
uint16_t OCFFlag : 1;
//-----------------//
uint8_t MasterChannelFrameCount;
uint8_t VirtualChannelFrameCount;
//-- Transfer Frame Data Field Status (2 octets) --//
uint16_t TransferFrameSecondaryHeaderFlag : 1;
uint16_t SyncFlag : 1;
uint16_t PacketOrderFlag : 1;
uint16_t SegmentLengthID : 2;
uint16_t FirstHeaderPointer : 11;
//-----------------//
};
Как я могу гарантировать, что LSB -> MSB сохранен в структуре?
Я все время путаюсь, и я пытался читать, но в итоге я запутался еще больше.
PS: я использую 32-битный процессор.
3 ответа
Как именно отображаются биты при использовании битовых полей, зависит от конкретной реализации. Так что очень трудно сказать наверняка, если бы вы все сделали правильно, нам нужно было бы знать точный процессор и компилятор (и версию компилятора, конечно).
Короче; не делай этого Битовые поля не очень пригодны для таких вещей.
Вместо этого сделайте это вручную, объявив слова по мере необходимости и установив биты внутри них.
ИМХО любой пытается построить struct
таким образом, находится в состоянии греха.
Стандарт C99, например, гласит:
Реализация может выделить любой адресуемый блок памяти, достаточно большой для хранения битового поля. Если остается достаточно места, битовое поле, которое непосредственно следует за другим битовым полем в структуре, должно быть упаковано в смежные биты той же единицы. Если остается недостаточно места, определяется, будет ли битовое поле, которое не помещается, в следующий блок или перекрывает соседние блоки, определяется реализацией. Порядок распределения битовых полей внутри блока (от старшего к младшему или от младшего к старшему) определяется реализацией. Выравнивание адресуемой единицы хранения не определено.
Даже если бы вы могли предсказать, что ваш компилятор будет создавать битовые поля в единицах (скажем) uint32_t, а поля были упорядочены в битах LS первого поля... у вас все еще есть порядок байтов!
Так что... как говорит раскрутка... делай это вручную!
Я согласен, что вы не должны этого делать. Однако STMicroelectronics использует битовые поля для доступа к битам своих регистров микроконтроллера Cortex-M3/M4. Поэтому любой поставщик компиляторов, который хочет, чтобы его пользователи могли использовать библиотеки STMicroelectronics Cortex-M3/M4, должен поддерживать выделение битовых полей, начиная с младшего бита. В моем компиляторе это значение по умолчанию, но оно также необязательно, поэтому я могу отменить его, если захочу.