联合声明的两种不同语法如何给我不同的大小?
How does the two different syntax of union declaration give me different size?
我在结构中声明一个联合数据类型(但有两种不同的语法)。对于结构的大小,我得到了不同的输出。这里有什么问题?
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);
}
我期望输出:8 8 16 16 但实际输出是 8 8 16 4。
s2
声明了一个联合但没有成为它的成员。
s1
正在使用 "anonymous union" 语义:(来自 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).
改变
struct s2 {
int a;
union u {
int b;
double c;
};
};
至
struct s2 {
int a;
union u {
int b;
double c;
} x;
};
你会得到相同的尺寸。
您的版本声明了一个内部类型,但没有创建 union u
的实例。
您的 s1
使用匿名联合,它有效地将您的联合实例注入 s1
但没有命名它。
基本上归结为对齐要求。对于 x86,基本类型的对齐要求是根据其大小对齐类型,即 4 字节类型将对齐 4 字节,8 字节类型将对齐 8 字节等。
在 x86 上,class/union 与其最大的原始成员对齐,即如果有 8 字节成员,则 class/union 将对齐 8 字节。
在 s1
的情况下,我们有一个 anonymous union,它被注入到外部范围(即它成为 s1
的一部分)
struct s1 {
int a;
union {
int b;
double c;
};
};
联合体的最大类型是double
,8 字节,因此联合体按8 字节对齐。编译器在 a
之后添加 4 个字节的填充以使联合对齐 8 个字节。
我们可以用这个来确认:
cout << offsetof(s1, a) << " " << offsetof(s1, b) << " " << offsetof(s1, c) << endl;
版画
0 8 8
如果s2
union u { ... };
是一个 声明 。它没有定义 u
类型的元素。所以 s2
只有一个成员 int a;
并且是 4 个字节长。
要将其更改为定义,请为其命名:union u { ... } u;
我在结构中声明一个联合数据类型(但有两种不同的语法)。对于结构的大小,我得到了不同的输出。这里有什么问题?
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);
}
我期望输出:8 8 16 16 但实际输出是 8 8 16 4。
s2
声明了一个联合但没有成为它的成员。
s1
正在使用 "anonymous union" 语义:(来自 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).
改变
struct s2 {
int a;
union u {
int b;
double c;
};
};
至
struct s2 {
int a;
union u {
int b;
double c;
} x;
};
你会得到相同的尺寸。
您的版本声明了一个内部类型,但没有创建 union u
的实例。
您的 s1
使用匿名联合,它有效地将您的联合实例注入 s1
但没有命名它。
基本上归结为对齐要求。对于 x86,基本类型的对齐要求是根据其大小对齐类型,即 4 字节类型将对齐 4 字节,8 字节类型将对齐 8 字节等。
在 x86 上,class/union 与其最大的原始成员对齐,即如果有 8 字节成员,则 class/union 将对齐 8 字节。
在 s1
的情况下,我们有一个 anonymous union,它被注入到外部范围(即它成为 s1
的一部分)
struct s1 {
int a;
union {
int b;
double c;
};
};
联合体的最大类型是double
,8 字节,因此联合体按8 字节对齐。编译器在 a
之后添加 4 个字节的填充以使联合对齐 8 个字节。
我们可以用这个来确认:
cout << offsetof(s1, a) << " " << offsetof(s1, b) << " " << offsetof(s1, c) << endl;
版画
0 8 8
如果s2
union u { ... };
是一个 声明 。它没有定义 u
类型的元素。所以 s2
只有一个成员 int a;
并且是 4 个字节长。
要将其更改为定义,请为其命名:union u { ... } u;