Это определенное поведение в C?
Это определенное поведение в C ++?
TL; DR: нет, это не так.
Логическое битовое поле четко определено, поскольку: bool
- это нормально используемый тип для битовых полей, поэтомувы гарантированно получите двоичный объект из 8 логических значений, выделенных где-то в памяти.Если вы получите логический _1
, вы получите то же значение, что и в прошлый раз, когда обращались к этой переменной.
То, что не определено, это битовый порядок.Компилятор может вставлять биты заполнения или байты заполнения по своему усмотрению.Все это определяется реализацией и не является переносимым.Таким образом, вы не можете точно знать, где находится _1
в памяти или это MSB или LSB.Ничто из этого не является четко определенным.
Однако, bits *b = (bits *)&c;
доступ к char
через указатель структуры является строгим нарушением псевдонимов и может также вызвать проблемы с выравниванием.Это неопределенное поведение в C и C ++.Вам, по крайней мере, нужно показать эту структуру в union
с char
, чтобы избежать строгого алиасинга, но вы все равно можете получить икоты выравнивания (и C ++ хмурится при пробивании типов через объединения).
(Ипереход от логического типа к символьному типу также может дать некоторые реальные сумасшедшие результаты, см. _Bool type и строгое псевдонимы )
Ничего из этого не удобно вообще - битовые поля очень плохо определены, намного лучше просто сделать:
c |= 1u << n; // set bit n
c &= ~(1u << n); // clear bit n
Это переносимый тип, не зависящий от типа и порядка байтов.
(Хотя, чтобы избежать изменения подписи из-за неявных целочисленных повышений, рекомендуется всегда приводить результат ~
обратно к предполагаемому типу: c &= (uint8_t) ~(1u << n);
).
Примечаниечто тип char
совершенно не подходит для побитовой арифметики, поскольку он может быть или не быть подписанным.Вместо этого вы должны использовать unsigned char
или предпочтительно uint8_t
.