Compiling my code as C++11 with gcc 4.8.2
and llvm/clang 3.4
on fedora-linux, I got strange results that I couldn't really explain...
here is a similar program fedora.
#include <iostream>
using namespace std;
struct A {};
struct C {};
struct B1 : A { union { A a;}; };
struct B2 : A { union { C c;}; };
int main()
{
cout << sizeof(B1) << " " << sizeof(B2) << endl;
}
sizeof(B1) = 2
and sizeof(B2) = 1
But why are the sizes different? Actually I have an idea "why", but I want to find the exact explanation or C++ rule.
The B1
child has both a parent and sub-object of type A
. Two distinct objects of the same type cannot exist at the same address, and the union separately contains an additional A
to the parent A
.
With B2
, the empty base optimization allows the empty A
parent and C
member to share the single address of the child.
I think that there will be helpful two quotes from the C++ Standard. The first one defines what is subobject.
2 Objects can contain other objects, called subobjects. A subobject can be a member subobject (9.2), a base class subobject (Clause 10), or an array element.
The second one says that two subobjects of the same type may not have the same address
A base class subobject may be of zero size (Clause 9); 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 (5.10). —end note ]
So in this class definition
struct B1 : A { union { A a;}; };
there are two subobjects of type A: base class subobject and member subobject a.
Also it is important to add that every member of every anonymous union is a member of the class containing the anonymous unions.
The C++11 standard can be interpreted to allow size 1 for both examples:
1.8 The C++ object model §6:
Unless an object is a bit-field or a base class subobject of zero size, the address of that object is the address of the first byte it occupies. Two distinct objects that are neither bit-fields nor base class subobjects of zero size shall have distinct addresses.
There's at least one non-normative notice disallowing it for case 1, but it is non-normative:
10 Derived classes §8:
[ Note: A base class subobject might have a layout (3.7) different from the layout of a most derived object of the same type. A base class subobject might have a polymorphic behavior (12.7) different from the polymorphic behavior of a most derived object of the same type. A base class subobject may be of zero size (Clause 9); 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 (5.10). —end note ]
The latest publicly available draft (n3797 dated 2013-10-13) though disallows the first example to have size 1:
1.8 The C++ object model §6:
Unless an object is a bit-field or a base class subobject of zero size, the address of that object is the address of the first byte it occupies. Two objects that are not bit-fields may have the same address if one is a subobject of the other, or if at least one is a base class subobject of zero size and they are of different types; otherwise, they shall have distinct addresses.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With