Namespaces
Variants

Bit-fields

From cppreference.net

Объявляет член с явно заданной шириной в битах. Смежные битовые поля могут быть упакованы вместе для совместного использования и пересечения отдельных байтов.

Объявление битового поля — это struct или union объявление члена, которое использует следующий декларатор :

идентификатор  (необязательно) : ширина
identifier - имя объявляемого битового поля. Имя является необязательным: безымянные битовые поля вводят указанное количество битов заполнения
width - целочисленное константное выражение со значением больше или равным нулю и меньше или равным количеству битов в базовом типе. Когда значение больше нуля, это количество битов, которое будет занимать данное битовое поле. Значение ноль разрешено только для безымянных битовых полей и имеет особое значение: оно указывает, что следующее битовое поле в определении класса начнется на границе единицы распределения памяти.

Содержание

Объяснение

Битовые поля могут иметь только один из следующих (возможно const или volatile квалифицированных) типов:

  • unsigned int , для беззнаковых битовых полей (например, unsigned int b : 3 ; имеет диапазон [ 0 , 7 ] )
  • signed int , для знаковых битовых полей ( signed int b : 3 ; имеет диапазон [ - 4 , 3 ] )
  • int , для битовых полей с определяемой реализацией знаковостью (обратите внимание, что это отличается от значения ключевого слова int во всех остальных контекстах, где оно означает "signed int"). Например, int b : 3 ; может иметь диапазон значений [ 0 , 7 ] или [ - 4 , 3 ] .
  • _Bool , для однобитовых битовых полей (например, bool x : 1 ; ) имеет диапазон [ 0 , 1 ] и неявные преобразования в него и из него следуют правилам булевых преобразований.
(начиная с C99)
  • биточно-точные целочисленные типы (например, _BitInt ( 5 ) : 4 ; имеет диапазон [ - 8 , 7 ] и unsigned _BitInt ( 5 ) : 4 ; имеет диапазон [ 0 , 15 ] ).
(начиная с C23)

Дополнительные типы, определяемые реализацией, могут быть допустимы. Также определяется реализацией, может ли битовое поле иметь atomic тип. (since C11) Количество битов в битовом поле ( width ) устанавливает предел диапазона значений, которые оно может хранить:

#include <stdio.h>
struct S
{
    // трёхбитное беззнаковое поле,
    // допустимые значения 0...7
    unsigned int b : 3;
};
int main(void)
{
    struct S s = {7};
    ++s.b; // беззнаковое переполнение
    printf("%d\n", s.b); // вывод: 0
}

Несколько смежных битовых полей могут быть (и обычно бывают) упакованы вместе:

#include <stdio.h>
struct S
{
    // обычно занимает 4 байта:
    // 5 бит: значение b1
    // 11 бит: не используется
    // 6 бит: значение b2
    // 2 бита: значение b3
    // 8 бит: не используется
    unsigned b1 : 5, : 11, b2 : 6, b3 : 2;
};
int main(void)
{
    printf("%zu\n", sizeof(struct S)); // обычно выводит 4
}

Специальное неназванное битовое поле с width нулевой ширины разрывает заполнение: оно указывает, что следующее битовое поле начинается в начале следующей единицы распределения:

#include <stdio.h>
struct S
{
    // обычно занимает 8 байт:
    // 5 бит: значение b1
    // 27 бит: не используется
    // 6 бит: значение b2
    // 15 бит: значение b3
    // 11 бит: не используется
    unsigned b1 : 5;
    unsigned    : 0; // начинает новый unsigned int
    unsigned b2 : 6;
    unsigned b3 : 15;
};
int main(void)
{
    printf("%zu\n", sizeof(struct S)); // обычно выводит 8
}

Поскольку битовые поля не обязательно начинаются с начала байта, адрес битового поля не может быть взят. Указатели на битовые поля невозможны. Битовые поля не могут использоваться с sizeof и _Alignas (начиная с C11) (до C23) alignas (начиная с C23) (начиная с C11) .

Примечания

Следующие варианты использования битовых полей приводят к неопределённому поведению :

  • Вызов offsetof на битовом поле.

Следующие свойства битовых полей являются неуточнёнными :

  • Выравнивание единицы распределения, содержащей битовое поле.

Следующие свойства битовых полей являются определяемыми реализацией :

  • Обрабатываются ли битовые поля типа int как знаковые или беззнаковые.
  • Разрешены ли типы, отличные от int , signed int , unsigned int , _Bool (since C99) , и (возможно unsigned ) _BitInt ( N ) (since C23) .
  • Разрешены ли атомарные типы.
(начиная с C11)
  • Может ли битовое поле пересекать границу единицы распределения.
  • Порядок расположения битовых полей внутри единицы распределения (на некоторых платформах битовые поля упаковываются слева направо, на других — справа налево).

Несмотря на то, что количество битов в представлении объекта _Bool составляет не менее CHAR_BIT , ширина битового поля типа _Bool не может превышать 1 .

(начиная с C99)

В языке программирования C++ ширина битового поля может превышать ширину базового типа (но дополнительные биты являются битами заполнения), и битовые поля типа int всегда являются знаковыми.

Ссылки

  • Стандарт C23 (ISO/IEC 9899:2024):
  • 6.7.2.1 Спецификаторы структур и объединений
  • Стандарт C17 (ISO/IEC 9899:2018):
  • 6.7.2.1 Спецификаторы структур и объединений
  • Стандарт C11 (ISO/IEC 9899:2011):
  • 6.7.2.1 Спецификаторы структур и объединений
  • Стандарт C99 (ISO/IEC 9899:1999):
  • 6.7.2.1 Спецификаторы структур и объединений
  • Стандарт C89/C90 (ISO/IEC 9899:1990):
  • 3.5.2.1 Спецификаторы структур и объединений

Смотрите также

C++ documentation для Bit-field