Является ли тип битового поля влияющим на выравнивание структуры
У меня есть следующие структуры:
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
.
Однако правила выравнивания для агрегатов, содержащих битовые поля, различаются в зависимости от действующего режима выравнивания.
Эти правила описаны здесь.
Ответ 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 внутри поля бит, определяется ли реализация. Таким образом, код может даже не работать.
Невозможно сказать, что будет делать этот код, не говоря уже о том, как он будет влиять на выравнивание, не просматривая документацию для конкретного компилятора.