Предположим, у меня есть структура, которая содержит другие структуры, которые не упакованы:
struct ContainerOfNonPacked
{
NonPacked1 first;
NonPacked2 second;
};
И тогда у меня есть структура, которая содержит другие структуры, которые упакованы:
struct ContainerOfPacked
{
Packed1 first; // declaration of struct had __attribute__((packed))
Packed2 second; // ditto
};
Первый не будет упакован компилятором (то есть нет гарантии, что внутри структуры не будет «дыр»). Возможно, в нем нет дыр, но вопрос не в этом.
Как насчет второго контейнера, который содержит упакованные структуры? Есть ли гарантия что структура, состоящая исключительно из упакованных структур как ее полей, сама упакована?
Редактировать: это зависит от компилятора и не зависит от поведения.
Для случая GCC и clang структуры, которые содержат только упакованные структуры, сами «упакованы». У них не будет никаких дополнительных «дырок» в них.
Вот пример, чтобы проиллюстрировать (ссылка Godbolt: https://godbolt.org/g/2noSpP):
У нас есть четыре структуры: Packed1, Packed2, NonPacked1 и NonPacked2.
#include <cstdint>
struct Packed1
{
uint32_t a;
uint64_t b;
} __attribute__((packed));
struct NonPacked1
{
uint16_t a;
// Padding of 2 bytes
uint32_t b;
uint8_t c;
};
// We have two structs of the same size, one packed and one not
static_assert(sizeof(NonPacked1) == 12);
static_assert(sizeof(Packed1) == 12);
struct Packed2
{
uint64_t a;
uint64_t b;
} __attribute__((packed)); // packing has no effect, but better for illustration
struct NonPacked2
{
uint32_t a;
// Padding of 4 bytes
uint64_t b;
};
// And again, two structs of the same size
static_assert(sizeof(Packed2) == 16);
static_assert(sizeof(NonPacked2) == 16);
Packed1 и Packed2 входят в структуру ContainerOfPacked, а два других — в ContainerOfNonPacked.
struct ContainerOfNonPacked
{
NonPacked1 first; // 12 bytes
// Padding of 4 bytes between the non-packed struct-fields
NonPacked2 second; // 16 bytes
};
struct ContainerOfPacked
{
Packed1 first; // 12
// No padding between the packed struct-fields
Packed2 second; // 16
};
static_assert(sizeof(ContainerOfNonPacked) == 32);
static_assert(sizeof(ContainerOfPacked) == 28);
Как показывают комментарии кода и статические утверждения, в контейнере упакованных структур нет отверстий для заполнения. Он ведет себя так, как будто он сам «упакован».
Хотя это и есть ответ, я также ищу ответы, которые могут привести соответствующие части Стандарта или некоторые другие авторитетные / теоретические объяснения.
Других решений пока нет …