Spec-Zone.ru › C

Битовые поля

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

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

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

Пояснение

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

  • unsignedint, для беззнаковых битовых полей (например, unsigned int b : 3; имеет диапазон [0, 7])
  • signedint, для знаковых битовых полей (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)

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

#include <stdio.h>

struct S
{
    // three-bit unsigned field,
    // allowed values are 0...7
    unsigned int b : 3;
};

int main(void)
{
    struct S s = {7};
    ++s.b; // unsigned overflow
    printf("%d\n", s.b); // output: 0
}

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

#include <stdio.h>

struct S
{
    // will usually occupy 4 bytes:
    // 5 bits: value of b1
    // 11 bits: unused
    // 6 bits: value of b2
    // 2 bits: value of b3
    // 8 bits: unused
    unsigned b1 : 5, : 11, b2 : 6, b3 : 2;
};

int main(void)
{
    printf("%zu\n", sizeof(struct S)); // usually prints 4
}

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

#include <stdio.h>

struct S
{
    // will usually occupy 8 bytes:
    // 5 bits: value of b1
    // 27 bits: unused
    // 6 bits: value of b2
    // 15 bits: value of b3
    // 11 bits: unused
    unsigned b1 : 5;
    unsigned    : 0; // starts a new unsigned int
    unsigned b2 : 6;
    unsigned b3 : 15;
};

int main(void)
{
    printf("%zu\n", sizeof(struct S)); // usually prints 8
}

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

Примечания

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

  • Вызов offsetof для битового поля.

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

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

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

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

Хотя количество битов в представлении объекта типа _Bool не меньше CHAR_BIT, width битового поля типа _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++ для битового поля

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/c/language/bit_field

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API