битовые поля и определения stdint - PullRequest
1 голос
/ 06 ноября 2011

Так что я программирую на C ++, и, насколько я могу судить, C ++ не эквивалентен stdint.h.Это не проблема, поскольку вы можете просто взять копию stdint и включить ее ... но мой вопрос в основном такой:

В чем разница между этими двумя частями кода:

struct FREQ{
    unsigned int FREQLOHI :16;
    //etc...

};

и

struct FREQ{
    uint16_t FREQLOHI;
    //etc...
}

, кроме очевидных ограничений битовых полей, есть ли проблема производительности / переносимости?Что предпочтительнее?

Ответы [ 2 ]

4 голосов
/ 06 ноября 2011

Разница в том, что unsigned int может иметь разный размер на разных платформах, в то время как uint16_t гарантированно имеет ширину 16 бит.Это означает, что экземпляр первой (битовой) структуры может иметь разный размер на разных платформах.Кроме того, доступ к битовым полям более дорогой, так как он требует дополнительного сдвига и маски.

Например, на ноутбуке, где unsigned int имеет ширину 32 бита, первая структура имеет ширину 32 бита, а вторая - 16-битная.

Когда дело доходит до переносимости, битовые поля находятся в гораздо более чистой ситуации, поскольку это старая функция языка C, которая была включена в C ++, когда она была стандартизирована в 1998 году (ISO / IEC 14882: 1998).С другой стороны, stdint.h был добавлен в C только в 1999 году (стандарт ISO / IEC 9899: 1999) и, следовательно, не является частью C ++ 98 (ISO / IEC 14882: 1998).Соответствующий заголовок cstdint затем был включен в C ++ TR1, но он поместил все идентификаторы в пространство имен std::tr1.Boost также предложил заголовок.Самый последний стандарт C ++ (C ++ 11 или ISO / IEC 14882: 2011, выпущенный в сентябре 2011 года) включает заголовок cstdint и помещает все идентификаторы в пространство имен std.Несмотря на это, cstdint широко поддерживается.

2 голосов
/ 06 ноября 2011

Компиляторы, как правило, собирают битовые поля в одно слово, уменьшая тем самым общий размер вашей структуры.Эта упаковка осуществляется за счет более медленного доступа к элементам битового поля.Например:

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, я обычно использую битовые поля для сжатия этих логических флагов в одном слове.

...