Битовое поле - это способ выравнивания данных?
Из cppreference
#include <iostream>
struct S {
// will usually occupy 2 bytes:
// 3 bits: value of b1
// 2 bits: unused
// 6 bits: value of b2
// 2 bits: value of b3
// 3 bits: unused
unsigned char b1 : 3, : 2, b2 : 6, b3 : 2;
};
int main()
{
std::cout << sizeof(S) << '\n'; // usually prints 2
}
Почему эти 2 бита не используются?
Не могло быть просто:
unsigned char b1 : 3, b2 : 6, b3 : 2;
Это способ заполнения?
Может ли кто-нибудь объяснить мне, действительно ли (если я не ошибаюсь) эти битовые поля изменяют размер переменной или они просто "предложение" для компилятора? (какinline
ключевое слово). Если битовые поля работают, как я понимаю, вы сможете хранить логическое значение в 1 бите (что невозможно, потому что память разделена на блоки по 1 байту)
2 ответа
Приведенный вами пример используется для объяснения того, что несколько битовых полей обычно (не обязательно) упаковываются вместе. Если присмотреться внимательнее:
// 3 bits: value of b1 - 3 bits occupied
// 2 bits: unused - 2 bits left unused
// 6 bits: value of b2 - 6 bits occupied (these 6 can't fit into the previous byte
as 5 bits are already occupied. What will happen in this
case? Will these 6 bits go into the next byte? Will they
somehow *overlap* two bytes?
// 2 bits: value of b3
// 3 bits: unused
Если результат sizeof(S) == 2
верно, то можно сказать, что поле b2
это трансзональные байты. Пример пытается объяснить эту концепцию.
Пример не так ясно объясняет это, поэтому позвольте мне создать немного лучший вариант:
struct S {
unsigned char b1 : 3, : 2, b2 : 6, b3 : 3;
};
Разница в том b3
теперь 3 бита. Общее количество бит структуры =3 + 2 + 6 + 3 = 14
. Если я напечатаюsizeof (S)
теперь я понимаю, 3
как результат, который говорит мне, что в моей системе нет байтов.
Кроме того, вы можете найти это внизу страницы:
- Все о фактических деталях распределения битовых полей в объекте класса
- Например, на некоторых платформах битовые поля не охватывают байты, на других - нет.
- Кроме того, на некоторых платформах битовые поля упаковываются слева направо, на других - справа налево.
Может ли кто-нибудь объяснить мне, действительно ли (если я не ошибаюсь) эти битовые поля изменяют размер переменной или они просто "предложение" для компилятора? (как встроенное ключевое слово). Если битовые поля работают, как я понимаю, вы сможете хранить логическое значение в 1 бите (что невозможно, потому что память разделена на куски по 1 байту)
Практически все, что касается битовых полей, определяется реализацией, поэтому для получения правильных ответов вам нужно будет просмотреть документацию каждого компилятора и прочитать документы ABI, чтобы получить ответ. Например, это из документов GCC:
Может ли битовое поле охватить границу единицы хранения (C90 6.5.2.1, C99 и C11 6.7.2.1).
Определяется ABI.
Если мы посмотрим на сборку генерироваться для GCC 10.1, мы можем видеть, что битовые поля являются на самом деле используются:
# b1: 1, b2: 61, b3: 3
sub rsp, 24
mov eax, -767
lea rdi, [rsp+14]
mov WORD PTR [rsp+14], ax
Номер -767
в двоичном формате:
b3 b6 b1
11 111101 00000001
логическое значение 1 бит
Ответ не был бы полным без упоминания std::vector<bool>
который пытался это сделать, но оказалось, что это не такая уж и хорошая идея.
Пример cppreference просто говорит о том, что в стандарте нет гарантии, что битовые поля отображаются в соседние области памяти, хотя в большинстве разумных реализаций это можно сделать. Предоставленный фрагмент кода намеренно использует безымянный битовый файл из 2 битов для запроса двух битов из хранилища - и просто демонстрирует, что битовые файлы могут быть безымянными. Таким образом, общее количество битов, необходимых для представления этой структуры, составляет 14.
14 бит могут быть упакованы в 2 байта (16 бит), так что это то, что ожидается от средней реализации, но не гарантируется.
И последнее, но не менее важное: если вы обнаружите, что можете использовать битовые поля в структуре, подумайте не дважды, а трижды. Существует очень мало сценариев, когда они действительно дают преимущество, поэтому вы должны быть уверены, что имеете дело с одним из них.