Упакованы ли структуры, содержащие упакованные структуры? - PullRequest
0 голосов
/ 10 мая 2018

Предположим, у меня есть структура, которая содержит другие структуры, которые не упакованы:

struct ContainerOfNonPacked
{
    NonPacked1 first;
    NonPacked2 second;
};

И тогда у меня есть структура, которая содержит другие упакованные структуры:

struct ContainerOfPacked
{
    Packed1 first; // declaration of struct had __attribute__((packed))
    Packed2 second; // ditto
};

Первое не будет упаковано компилятором (то есть нет гарантии, что внутри структуры не будет "дыр"). Возможно, у него нет дыр, но вопрос не в этом.

А как насчет второго контейнера, который содержит упакованные структуры? Есть ли гарантия , что структура, состоящая исключительно из упакованных структур в качестве своих полей, сама упакована?

1 Ответ

0 голосов
/ 10 мая 2018

Редактировать: все зависит от компилятора и не зависит от поведения.

В случае 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);

Как показывают комментарии к коду и статические утверждения, в контейнере упакованных структур нет отверстий для заполнения. Он ведет себя так, как будто он сам "упакован".

Хотя это ответ, я также ищу ответы, которые могут привести соответствующие части Стандарта или некоторые другие авторитетные / теоретические объяснения.

...