Является ли тип битового поля влияющим на выравнивание структуры

У меня есть следующие структуры:

struct bf_struct1
{
    uint64_t bf1 : 1;
    uint64_t bf2 : 6;
    uint64_t bf3 : 2;
    uint64_t bf4 : 55;
}

struct bf_struct2
{
    uint8_t bf1 : 1;
    uint8_t bf2 : 6;
    uint8_t bf3 : 2;
    uint64_t bf4 : 55;
}

Соответствует ли выравнивание элемента структуры типу элементов битового поля?

Ответы

Ответ 1

Из лошадиного устья:

6.7.2.1 Спецификаторы структуры и объединения
...
5 Битовое поле должно иметь тип, который является квалифицированной или неквалифицированной версией _Bool, signed int, unsigned int или некоторым другим определенным для реализации типом. это реализация - определяется, разрешены ли атомные типы.
...
11 Реализация может выделить любой адресный блок хранения, достаточно большой для хранения битового поля. Если остается достаточно места, бит-поле, которое сразу же следует за другим битовым полем в структура должна быть упакована в соседние биты того же блока. Если недостаточно места, будет ли бит-поле, которое не подходит, помещается в следующий блок или перекрывает смежные единицы реализации. Порядок распределения бит-полей внутри единицы (от высокого до с низким или низким порядком) определяется реализацией. Выравнивание адресный блок хранения не указан.

Короткий ответ: он может, в зависимости от реализации.

Ответ 2

Does the structure member alignment depend on type of a bitfield members?  

Да.

Проверьте byte offset и bit offset.

Однако правила выравнивания для агрегатов, содержащих битовые поля, различаются в зависимости от действующего режима выравнивания. enter image description here

Эти правила описаны здесь.

Ответ 3

Да, это может повлиять на него. В первом приведенном примере все поля могут вписываться в один 64-разрядный uint64-t, поэтому структура, вероятно, занимает всего 8 байтов. Во втором случае, скорее всего, это будет 16 байт. Для первых трех полей потребуется не менее двух байтов (два uint8_t). Тогда последнее поле бит из 55 бит займет один uint64_t, который, вероятно, будет выровнен по 8-байтовой границе. Таким образом, хотя фактический макет зависит от компилятора, положение бит будет отличаться в обоих примерах (из-за предполагаемого заполнения до uint64_t во втором примере.

Макет, скорее всего, будет выглядеть следующим образом (не точно для масштабирования):

bf_struct1

+---------------+---------+---------+-----------------------------------+
|    uint8_t    | uint8_t | Padding | uint64_t                          |
+---------------+---------+---------+-----------------------------------+
| bf1, bf2, bf3           | 48-bits | bf4                               |
+---------------+---------+---------+-----------------------------------+

bf_struct2

+-----------------------------------+
|      uint64_t                     |
+-----------------------------------+
| bf1, bf2, bf3, bf4                |
+-----------------------------------+

Ответ 4

#include <stdio.h>

#define uint64_t unsigned long long
#define uint8_t unsigned char

struct bf_struct1
{
    uint64_t bf1 : 1;
    uint64_t bf2 : 6;
    uint64_t bf3 : 2;
    uint64_t bf4 : 55;
};

struct bf_struct2
{
    uint8_t bf1 : 1;
    uint8_t bf2 : 6;
    uint8_t bf3 : 2;
    uint64_t bf4 : 55;
};
int main(){
    printf("%lu ", sizeof(struct bf_struct1));
    printf("%lu ", sizeof(struct bf_struct2));
    return 0;
}

Результаты в 8 16. Итак, я бы сказал, что ответ "да". Зависит от компилятора даже хотя gcc и clang согласны с моей машиной. Вы можете сделать несколько союзов и точно укажите, что такое выравнивание.

Ответ 5

  • Выравнивание битового поля в целом является неопределенным поведением и может ли битовое поле разрешать выделение без выравнивания - это поведение, определяемое реализацией.
  • Порядок бит битового поля определяется реализацией.
  • Из-за двух замечаний выше, компилятор может свободно добавлять биты дополнений и байты заполнения в любом месте битового поля, как это угодно, в соответствии с реализацией.
  • Разрешено ли uint64_t внутри поля бит, определяется ли реализация. Таким образом, код может даже не работать.

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