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