Spec-Zone.ru › C

Битовые поля

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

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

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

Объяснение

Битовые поля могут иметь только один из этих трех(до C99) – четырех(с C99)(до C23) типов (возможно, с квалификаторами 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 и неявные преобразования к нему и от него следуют правилам преобразования boolean.
(с C99)
  • целочисленные типы с точностью до бита. (например, _BitInt(5):4; имеет диапазон -8..7 и unsigned _BitInt(5):4; имеет диапазон 0..15).
(с C23)

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

#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
}

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

#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; // start 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).

Примечания

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

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

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

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

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

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

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

(с C99)

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

Ссылки

  • Стандарт C23 (ISO/IEC 9899:2023):
    • 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/w/c/language/bit_field

Spec-Zone.ru

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