Reputation: 80
I am declaring a union data type inside a struct (but two different syntax). I get different output for the size of the structs. What's the catch here?
union u {
double x;
int y;
};
union {
double x;
int y;
} u_1;
struct s1 {
int a;
union {
int b;
double c;
};
};
struct s2 {
int a;
union u{
int b;
double c;
};
};
int main()
{
u u1;
s1 s_1;
s2 s_2;
cout<< sizeof(u1)<< " "<<sizeof(u_1)<<" " <<sizeof(s_1)<<" " <<sizeof(s_2);
}
I expected the output: 8 8 16 16 but the actual output is 8 8 16 4.
Upvotes: 3
Views: 319
Reputation: 85481
Basically it comes down to alignment requirements. For x86, the alignment requirements for primitive types are to align the type on its size, i.e. a 4-byte type will be aligned on 4 bytes, an 8-byte type on 8 bytes, etc.
On x86, a class/union is aligned on the largest of its primitive members, i.e. if there is an 8-byte member, the class/union will be aligned on 8 bytes.
In case of s1
we have an anonymous union, which is injected into the outer scope (i.e. it becomes part of s1
)
struct s1 {
int a;
union {
int b;
double c;
};
};
The union's largest type is double
, 8 bytes so the union is aligned on 8 bytes. The compiler adds 4 bytes of padding after a
to get the union to align on 8 bytes.
We can confirm it with this:
cout << offsetof(s1, a) << " " << offsetof(s1, b) << " " << offsetof(s1, c) << endl;
Prints
0 8 8
In case of s2
union u { ... };
is a declaration. It defines no element of type u
. So s2
has only one member, int a;
and is 4 bytes long.
To change it into a definition, give it a name: union u { ... } u;
Upvotes: 1
Reputation: 88007
Change
struct s2 {
int a;
union u {
int b;
double c;
};
};
to
struct s2 {
int a;
union u {
int b;
double c;
} x;
};
and you'll get the same size.
Your version declares an inner type but does not create an instance of union u
.
Your s1
uses an anonymous union which effectively does inject an instance of your union into s1
but without naming it.
Upvotes: 2
Reputation: 687
s2
declares a union but makes no member of it.
s1
is using "anonymous union" semantics: (from https://en.cppreference.com/w/cpp/language/union)
Members of an anonymous union are injected in the enclosing scope (and must not conflict with other names declared there).
Upvotes: 7