Представьте себе! Я получаю 8 байтов как uint8_t data[8]
от интерфейса ввода-вывода, который обрабатывает некоторую автоматизацию дома. Эти восемь байт должны быть интерпретированы как залежи:Как получить доступ к битам в отображаемой памяти?
Как получить доступ правильных бит? Я думал, сейчас около двух решений:
Решение 1: Определение-структуру с некоторыми битовых полей:
struct data_s {
uint8_t LightSwitch0:1;
uint8_t LightSwitch1:1;
uint8_t LightSwitch2:1;
uint8_t LightSwitch3:1;
uint8_t Brightness:4;
uint8_t Dimmer0;
uint8_t Dimmer1;
uint8_t Dimmer2;
uint8_t Dimmer3;
uint8_t Dimmer4;
uint8_t DoorSwitch:1;
uint8_t Spare:7;
}
Далее я мог бы просто сделать слепок и получить доступ к членам структур согласно этому примеру:
data_s *foo = data;
foo->LightSwtich1 = FALSE;
foo->Brightness = 7;
//...
Решение 2: Используйте битмаски:
data[0] |= 0x02;
data[0] = (data[0] & 0x0F) | ((7 << 4) & 0xF0)
//...
Ну, я знаю, что битподы являются компилятором и зависят от этого. Вот почему решение 2 часто является предпочтительным. Тем не менее решение 2 выглядит намного сложнее и труднее читать. Более того, было бы много работать, если отображаемая память имеет более восьми байтов.
Нужно ли мне делать решение2? Или я мог бы использовать директиву #pragma reverse_bitfields on
, чтобы улучшить переносимость решения 1? Могу ли я использовать решение 1, если код построен только для одной цели с помощью кросс-компилятора?
Так что мой вопрос: Как получить доступ к правильным битам?
Битвы являются переносными и частью стандарта C. Это вопрос читаемости кода и привычек: в моем случае я предпочитаю битмаски, но многие люди предпочитают битфилды. – LPs
MISRA используется для запрета использования битполей, я не знаю, все ли это делает. – Toby
Вы можете сделать решение 2 более просто читаемым, используя макросы #define. В конечном итоге вы получите уродливые нечитаемые материалы в одном месте, что добавит преимущества сокращения объема работы, необходимой для внесения изменений в будущем. –