Bit-fields
Объявляет член с явно заданной шириной в битах. Смежные битовые поля могут быть упакованы вместе для совместного использования и пересечения отдельных байтов.
Объявление битового поля — это 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].
|
(начиная с C99) |
|
(начиная с 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
|