结构体(Struct)定义:
struct 结构体名 {
member1; // 成员1,可以是任何基本数据类型或复合类型
member2; // 成员2
...
};
//例如:
struct Point {
float x;
float y;
};
联合体(Union)定义:
union 联合体名 {
member1; // 成员1
member2; // 成员2
...
};
//例如:
union Data {
int i;
float f;
char str[20]; // 联合体的大小将由最大的成员决定,这里是str[20]
};
struct 与 union 的对比
struct(结构体)和union(联合体)都是C语言中用于创建由多个不同类型的成员组成的自定义数据类型。尽管它们在某些方面相似,但它们之间存在一些关键的区别:
-
内存分配:
struct:结构体的所有成员都存储在内存中,每个成员都有自己的内存地址。结构体的大小是其所有成员大小的总和。
union:联合体的所有成员共享同一块内存空间。联合体的大小等于其最大成员的大小。 -
数据存储:
struct:可以同时存储所有成员的数据,即使它们是不同类型的。
union:一次只能存储一个成员的数据。当你访问联合体的某个成员时,其他成员的数据将被覆盖。 -
使用场景:
struct:当你需要同时存储多个不同类型的数据时,结构体是一个很好的选择。
union:当你需要使用同一块内存来存储不同类型的数据,但是一次只需要访问其中一个类型时,联合体是合适的。 -
内存效率:
struct:由于所有成员都存储在内存中,结构体可能不是内存效率最高的选择。
union:由于所有成员共享内存,联合体可以节省内存,特别是在你需要存储多个大型数据类型时。 -
访问方式:
struct:可以同时访问结构体的所有成员,只要它们不违反内存对齐和打包规则。
union:一次只能访问一个成员。访问其他成员之前,通常需要先清除当前成员的数据。 -
初始化:
struct:可以初始化结构体的所有成员。
union:只能初始化联合体的第一个成员。其他成员在初始化时不会被赋值。 -
成员的const属性:
struct:结构体的成员可以是const,这意味着它们的值一旦初始化就不能被修改。
union:联合体的成员不能是const,因为它们可以被其他类型的成员覆盖。 -
内存对齐:
struct:结构体的布局可能会受到内存对齐的影响,导致存在填充字节。
union:联合体的布局通常不会有填充字节,因为它们的大小取决于最大成员的大小。
struct位字段
位字段允许你指定结构体成员占用的位数,这可以用来精确控制成员的大小。
struct MyStruct {
unsigned int is_enabled : 1; // 占用1位
unsigned int has_data : 1; // 占用1位
// 剩余的位可以留给其他成员
};
struct packed属性
某些编译器提供了packed属性来禁用结构体的自然对齐,这可能会导致结构体成员紧密排列,从而减少填充字节。
#pragma pack(push, 1)
struct MyStruct {
int a;
char b;
};
#pragma pack(pop)