Компиляторы, как правило, собирают битовые поля в одно слово, уменьшая тем самым общий размер вашей структуры.Эта упаковка осуществляется за счет более медленного доступа к элементам битового поля.Например:
struct Bitfields
{
unsigned int eight_bit : 8;
unsigned int sixteen_bit : 16;
unsigned int eight_bit_2 : 8;
};
Может быть упакован как
0 8 24
-----------------------------------------------------
| eight_bit | sixteen_bit | eight_bit_2 |
-----------------------------------------------------
Каждый раз, когда вы получаете доступ к sixteen_bit
, он подвергается сдвигу и битам и операции.
С другой стороныстороны, если вы сделаете
struct NonBitfields
{
uint8_t eight_bit;
uint16_t sixteen_bit;
uint8_t eight_bit_2;
};
, то компилятор обычно выравнивает элементы по границам слов и размещает их примерно так:
0 8 16 24
-----------------------------------------------------
| eight_bit | | sixteen_bit |
-----------------------------------------------------
| eight_bit_2| |
-----------------------------------------------------
Это тратит больше места по сравнению с битовыми полями, нок элементам можно получить доступ быстрее без смещения битов и маскирования.
Вот некоторые другие различия:
- Вы не можете применить
sizeof
к элементу битового поля. - Вы не можете передать элемент битового поля по ссылке.
С точки зрения переносимости, оба варианта должны работать на любом совместимом со стандартами компиляторе.Если вы имеете в виду двоичную переносимость между различными платформами при записи структуры в файл или сокет, то все ставки отключены для любого случая.
С точки зрения предпочтений, я бы выбрал использование uint16_t
вместо битовых полей, если нет веской причины для упаковки полей вместе для экономии места.Если у меня внутри структуры много bool
, я обычно использую битовые поля для сжатия этих логических флагов в одном слове.