Существуют ли причины для исключения элементов структуры битового поля?
Я давно знал, что в C есть бит-поля, а иногда я использую их для определения плотно упакованных структур:
typedef struct Message_s {
unsigned int flag : 1;
unsigned int channel : 4;
unsigned int signal : 11;
} Message;
Когда я читаю открытый исходный код, вместо этого я часто нахожу бит-маски и операции смены битов для хранения и извлечения такой информации в ручных бит-полях. Это настолько распространено, что я не думаю, что авторы не знали о синтаксисе битового поля, поэтому я задаюсь вопросом, есть ли причины перебрасывать бит-поля с помощью бит-масок и выполнять операции переключения самостоятельно, вместо того чтобы полагаться на компилятор для генерации код для получения и установки таких битовых полей.
Ответы
Ответ 1
Почему другие программисты используют ручные манипуляции вместо битовых полей, чтобы упаковать несколько полей в одно слово?
Этот ответ основан на мнениях, поскольку вопрос достаточно открытый:
-
Многие программисты не знают о наличии битовых полей или не уверены в их переносимости и точной семантике. Некоторые даже не доверяют способности компилятора создавать правильный код. Они предпочитают писать явный код, который они понимают.
Как прокомментировал Cornstalks, это отношение уходит корнями в реальный жизненный опыт как описано в этой статье.
- Битовая область памяти - это реализация: если макет памяти должен соответствовать точной спецификации, битовые поля не должны использоваться, и могут потребоваться манипуляции с ручным кодированием.
- Передача подписанных значений в подписанных типизированных битовых полях определяется реализацией. Если подписанные значения упакованы в ряд битов, может быть более надежно вручную кодировать функции доступа.
Ответ 2
Есть ли причины, чтобы избежать битовых полей?
bitfield-structs имеют некоторые ограничения:
- Поля бит приводят к не переносимому коду. Кроме того, длина битового поля имеет большую зависимость от размера слова.
- Чтение (с использованием
scanf()
) и использование указателей в битовых полях невозможны из-за неадресности.
- Бит-поля используются для хранения большего количества переменных в меньшем пространстве данных, но заставляют компилятор генерировать дополнительный код для управления этими переменными. Это приводит к увеличению как пространственных, так и временных сложностей.
- Оператор
sizeof()
не может применяться к битовым полям, так как sizeof()
дает результат в байтах, а не в битах.
Source
Итак, следует ли вам их использовать или нет. Подробнее в Почему bit endianness является проблемой в битполях?
PS: Когда использовать бит-поля в C?
Ответ 3
Нет причин для этого. Битвы полезны и удобны. Они широко используются во встроенных проектах. Некоторые архитектуры (например, ARM) имеют даже специальные инструкции для управления битовыми полями.
Просто сравните код (и напишите остальные функции foo1)
https://godbolt.org/g/72b3vY
Ответ 4
Во многих случаях полезно иметь возможность адресовать отдельные группы битов в слове или работать над словом в виде единицы. Стандарт в настоящее время не предусматривает
любой практичный и переносимый способ достижения такой функциональности. Если код написан для использования битовых полей, и позже становится необходимым обращаться к нескольким группам как к слову, не было бы хорошего способа удовлетворить это, не перерабатывая весь код с использованием битовых полей или отключая оптимизацию псевдонимов на основе типов, используя функцию punning, и надеясь, что все будет расставлено, как ожидалось.
Использование смен и масок может быть неэлегантным, но до тех пор, пока C не предоставит средство для обработки явно определенной последовательности бит в пределах одного значения lvalue в качестве другого lvalue, это часто лучший способ обеспечить, чтобы код был адаптирован для удовлетворения потребностей.