结构体struct
是存储多个数据对象的内存块,这些对象不重叠。union
是一块内存,用于存储多个数据对象,但只能存储其中最大的一个,因此在任何时候只能存储一个数据对象。
union
和 struct
之间的主要区别在于 union
成员覆盖彼此的内存,因此 union
的 sizeof
= 1 ,而 struct
成员一个接一个地分布在内存里(在可选的填充之间分布)。union
也足够大以包含其所有成员,并且具有适合其所有成员的对齐方式。假设 int
只能存储在 2 个字节的地址并且是 2 个字节的宽度,而 long
只能存储在 4 个字节的地址并且是 4 个字节的长度。
struct
的内存大小
struct
的 sizeof
并不总是等于每个成员的 sizeof
总和。这是因为编译器添加了填充padding bytes以避免对齐问题。仅当结构体的成员后面有占有更多内存的成员,或在结构末尾时才添加填充padding。不同的编译器可能有不同的对齐约束。
例子
// C program to illustrate
// size of struct
#include <stdio.h>
int main()
{
struct A {
// sizeof(int) = 4
int x;
// Padding of 4 bytes
// sizeof(double) = 8
double z;
// sizeof(short int) = 2
short int y;
// Padding of 6 bytes
};
printf("Size of struct: %ld", sizeof(struct A));
return 0;
}
Size of struct: 24
内存图示:
红色部分表示为数据对齐添加的填充,绿色部分表示结构体成员。在这种情况下,x
(int
) 后跟 z
(double
),与 x 相比,z
的大小更大。因此在 x
之后添加了填充。此外,最后需要填充以进行数据对齐。
如果将double z;
注释掉,输出则为8。
还有一个更有意思的例子:
// C program to illustrate
// size of struct
#include <stdio.h>
int main()
{
struct B {
// sizeof(double) = 8
double z;
// sizeof(int) = 4
int x;
// sizeof(short int) = 2
short int y;
// Padding of 2 bytes
};
printf("Size of struct: %ld", sizeof(struct B));
return 0;
}
Size of struct: 16
在这种情况下,结构体的成员按其大小的降序排序。因此只在最后需要填充。
union
的存储方式和内存大小
每个成员共享相同的内存区域。最多只有一名成员占有当前内存。但你无法查明是哪一个成员,你必须自己将有关当前活动成员的信息存储在其他地方。
union
总是占用与最大成员一样多的空间。目前使用的是哪个成员并不重要。