Битовые поля VS. битмаски - PullRequest
2 голосов
/ 09 июля 2019

Раньше у меня был некоторый опыт работы с Си, однако я никогда раньше не видел функцию битовых полей. Я знаю, что можно использовать битовые маски для выделения определенных битов в структуре данных, но зачем тогда беспокоиться о битовых полях?

Например, скажем, биты, которые мы хотим выделить, это первые 3 младших бита. Тогда мы можем написать:

/* our bitmasks */
#define FIELD_A (1 << 0)
#define FIELD_B (1 << 1)
#define FIELD_C (1 << 2)

int main(void) 
{ 
    /* the data structure that contains our three fields */
    uint8_t flags;

    /* accessing field A (as a boolean) */
    int bool_a = !!(flags & FIELD_A);

    /* accessing field B (as a boolean) */
    int bool_b = !!(flags & FIELD_B);

    /* accessing field C (as a boolean) */
    int bool_c = !!(flags & FIELD_C);

    return 0;
}

Почему мы решили написать это как:

static struct fields {
    int field_a : 1;
    int field_b : 1;
    int field_c : 1;
};

int main(void) 
{ 
    /* the data structure that contains our three fields */
    struct fields flags;

    /* accessing field A */
    int bit_a = flags.a;

    /* accessing field B */
    int bit_b = flags.b;

    /* accessing field C */
    int bit_c = flags.c;

    return 0;
}

Ответы [ 2 ]

4 голосов
/ 09 июля 2019

Битовые поля удобнее использовать, чем явные битовые маски, особенно для длин, превышающих 1. Перекручивание битов с ручным кодированием довольно часто прерывается тонкими способами.

Основная проблема с битовыми полями - неточная спецификация:

  • определяется реализацией, могут ли типизированные битовые поля со знаком иметь отрицательные значения.

  • порядок и положение битовых полей в памяти определяются реализацией, что исключает более рискованное отображение оборудования. Даже для данного порядка байтов позиции и порядок битовых полей точно не определены, что является существенным недостатком.

Обратите внимание, в частности, что int field_a : 1; на самом деле неверно: битовое поле int с одним битом может читаться как -1 вместо 1, если установлено. Вы должны написать unsigned int field_a : 1;

0 голосов
/ 09 июля 2019

Я знаю, что можно использовать битовые маски для выделения определенных битов в структуре данных, но зачем тогда беспокоиться о битовых полях?

Один использует битовые поля либо для сопоставления структуры данных, размеры полей которой составляютне все соответствуют встроенным типам вашей реализации C, таким как заголовок TCP, или просто для уменьшения размера структуры данных.

Вы действительно можете упаковать и распаковать данные вручную, используя маски и смещения, но битовые поляпредоставить более удобный синтаксис для этого.Помимо простого скрытия смещения и маскирования, доступ к битовым полям прозрачно обрабатывает проблемы расширения знака и специальные характеристики _Bool, где это уместно.

Компромисс - это потеря контроля над деталями.Если вы упаковываете и распаковываете вручную, тогда вы можете быть полностью уверены в управлении и расположении, с большой мобильностью.Если вы используете битовые поля, с другой стороны, и , вы заботитесь о деталях их расположения, тогда вам нужно полагаться на детали реализации или расширения, чтобы гарантировать, что у вас есть требуемый макет,если это вообще возможно из вашей реализации.

...