MyTetra Share
Делитесь знаниями!
Битовые поля в C++ и синтаксис определения с одинарным двоеточием
Время создания: 25.11.2025 16:19
Текстовые метки: C++, Си++, язык, синтаксис, двоеточие, битовое, поле, класс, член, мембер, member, определение, маска
Раздел: Компьютер - Программирование - Язык C++ (Си++)
Запись: xintrea/mytetra_syncro/master/base/1764076753fq3p6ebres/text.html на raw.githubusercontent.com

Пример определения битовых полей (bit-fields) в классе:



struct PackedData {

unsigned char flag1 : 1; // Биты 0

unsigned char flag2 : 1; // Биты 1

unsigned char value : 6; // Биты 2-7

};



Здесь хорошо виден синтаксис объявления битового поля через одинарное двоеточие.


Ниже перечислены особенности битовых полей:



  • Все члены существуют одновременно
  • Каждый член занимает свою часть битов
  • Размер оптимизирован под общую сумму битов



В примере выше, в памяти будет выделен один 8-битовый байт, то есть, компилятор упаковывает биты автоматически. Когда происходит вышеуказанное объявление, то компилятор распределяет биты последовательно (внутри одного или нескольких байтов). Визуально это можно представить так:



Байт в памяти:


[7][6][5][4][3][2][1][0] ← биты

│ │ │ │ │ │ │ └── flag1 (бит 0)

│ │ │ │ │ │ └───── flag2 (бит 1)

│ │ │ │ │ └──────── (не используется)

└──┴──┴──┴──┴─────────── value (биты 2-7)


Визуализация размещения:


Память: | value (6 бит) | flag2 (1 бит) | flag1 (1 бит) |

Биты: | 7 6 5 4 3 2 | 1 | 0 |



Стандарт C++ явно позволяет компилятору размещать несколько битовых полей в одной единице памяти (в байте/слове). Когда происходит обращение к полям, компилятор под капотом генерирует специальные инструкции. Все это вместе позволяет достаточно просто устанавливать и считывать биты без применения масок и всяких сдвиговых инструкций. Код становится очень простым:



PackedData data;


data.flag1 = 1; // Компилятор генерирует: установить бит 0 в 1

data.value = 42; // Компилятор генерирует: записать в биты 2-7 число 42


"Наезжание" битовых полей в пределах одного байта происходит не как в union (перекрытие целых полей), а как последовательное распределение битов внутри единицы памяти, и это происходит под управлением компилятора.


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



  1. Битовые поля группируются в "юниты" (обычно размером с int)
  2. При смене типа или при заполнении юнита - начинается новый юнит
  3. Выравнивание может добавлять padding-байты



Это значит, что следующий тип занимает 3 байта:



struct PackedData {

unsigned char firstBits1 : 1; // Байт 0, биты 0-1

unsigned char firstBits2 : 1;

char a; // Байт 1 (может быть байт 2 из-за выравнивания)

unsigned char secondBits1 : 1; // Байт 2 для битовых полей, биты 0-1

unsigned char secondBits2 : 1;

};


Но с учетом выравнивания, может быть добавлен "пустой" 4-й байт, чтобы вся структура влезала в int.


Так же в этом разделе:
 
MyTetra Share v.0.67
Яндекс индекс цитирования