Размеры и наследование упакованных структур с разными компиляторами

Рассмотрим MWE:

#include <iostream>

struct A     {}         __attribute__((packed)) ;
struct B : A { int x; } __attribute__((packed)) ;

struct C : A { B y; }   __attribute__((packed)) ;

int main () {
std::cout << "Size of A: " << sizeof(A) << std::endl;
std::cout << "Size of B: " << sizeof(B) << std::endl;
std::cout << "Size of C: " << sizeof(C) << std::endl;
};

В Linux я попытался скомпилировать его и запустить:

$ g++ --version
g++ (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609

$ g++ ./test.cpp && ./a.out
Size of A: 1
Size of B: 4
Size of C: 5

Что касается А и Б, то все понятно. Но как насчет C? Что добавляет 1 байт к размеру C? Более того, если вы удалите любые отношения наследования, для B или C, C станет размером 4. Используя компиляторы MS (по крайней мере, один, поставляемый с VS 2013), я получил 1, 4 и 4 размера. Любые объяснения и детали по этому поводу приветствуются.

1

Решение

[class.derived] / 7 (стандартный проект)

… Субобъект базового класса может иметь нулевой размер (пункт [класс]); однако два подобъекта, которые имеют один и тот же тип класса и принадлежат к одному и тому же самому производному объекту, не должны размещаться по одному и тому же адресу ([expr.eq]). — конец примечания]

C имеет подобъекты B::A (основа участника y) а также C::A (прямая база), которые оба типа A, y в противном случае может быть по тому же адресу, что и пустая база C, но так как он также имеет базу того же типа, эта база B может не иметь один и тот же адрес и поэтому должен быть смещен с помощью отступа. GCC следует этому правилу и применяет только запрос упаковки к заполнению, которое было необходимо для правильного выравнивания.

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]