2

Consider a 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;
};

On Linux I tried to compile it and run:

$ 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

As for A and B everything is clear. But what about C? What adds 1 byte to the C's size? Moreover, if you'll remove any inheritance relationships, either for B or C, C become of size 4. Using MS compilers (at least one that is shipped with VS 2013), I got 1, 4 and 4 sizes. Any explanation and details on that are appreciated.

CaptainTrunky
  • 1,562
  • 2
  • 15
  • 23
  • 1
    Possible duplicate of [Why would the size of a packed structure be different on Linux and Windows when using gcc?](http://stackoverflow.com/questions/7789668/why-would-the-size-of-a-packed-structure-be-different-on-linux-and-windows-when) – MSD Feb 28 '17 at 07:14
  • @saranyadeviM, I've seen this question. To my opinion, it discusses reasons why structs could be packed in different ways in general (!). I'm more interested in how inheritance affects the packing's results and how exactly inheritance mixed with composition adds 1 byte to a struct's size. So, I believe that my question is more specific. :) – CaptainTrunky Feb 28 '17 at 07:28

1 Answers1

3

[class.derived] / 7 (standard draft)

... A base class subobject may be of zero size (Clause [class]); however, two subobjects that have the same class type and that belong to the same most derived object must not be allocated at the same address ([expr.eq]).  — end note ]

C has subobjects B::A (base of member y) and C::A (direct base) which are both of type A. y could otherwise be at the same address as the the empty base of C, but since it also has a base of same type, that base of B may not have the same address and therefore must be offset with padding. GCC follows this rule and only applies packing request to padding that was needed for correct alignment.

Community
  • 1
  • 1
eerorika
  • 232,697
  • 12
  • 197
  • 326
  • Sounds reasonable. This answers my original question, but rises another one: is it possible to break something when this assumption does not hold? The only thing that comes to mind is using pointers as keys to something. In this case they must be different. But it's rather exotic thing to do. – CaptainTrunky Feb 28 '17 at 08:35
  • @CaptainTrunky Good question. I think that any code that depends on this has to be quite convoluted, but that might be just lack of my imagination. Indeed something that deals with identity of objects, like using pointers to them as keys might be affected. – eerorika Feb 28 '17 at 09:01