Битовое поле - это способ выравнивания данных?

Из 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 бит), так что это то, что ожидается от средней реализации, но не гарантируется.

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

Другие вопросы по тегам