##C语言中联合union的正确用法。
假设你想用结构来模拟某样东西。但这个东西的属性可以用多种的数据类型来表示。
例如,一箱苹果你可以几种数据类型来表示:
- 1、一箱有10个苹果。(int)
- 2、一箱有2.5斤苹果。(float)
- 3、一箱有1.25公斤苹果。(float)
如果使用常规的结构体来表示的话:
typedef struct {
int number; // 苹果个数 4字节
float weight_half_KG; // 苹果重量(斤) 4字节
float weight_KG; // 苹果重量(公斤) 4字节
}Apple;
这不是一个好主意,因为结构体在内存中占用了更多的空间(结构体Apple占用了12个字节),无论用户是只使用了一个字段,还是三个字段都使用了。用户可能会既设置一箱苹果的数量,也设置了重量。
因此,我们会自然而然的想,如果有一种数据类型,可以根据我给出的数据来决定是使用何种数据类型就好了。当我给出的是整形数据,那就使用“int number”;如果我给出的是浮点数数据,根据需要使用“float weight_half_KG”或“float weight_KG”。而C语言中的联合就可以做到这点。
当定义联合时,计算机会为根据其中最大的字段分配空间。
typedef union {
int number; // 苹果个数 4字节
float weight_half_KG; // 苹果重量(斤) 4字节
float weight_KG; // 苹果重量(公斤) 4字节
}Apple;
在这里三个字段的都是4字节,因此计算机会分配4字节的内存空间给我们定义的联合变量使用。无论是设置了number,还是weight_half_KG,还是weight_KG,他们都会保存在内存中的同一个地方。而且长度只有4个字节。
我们可以使用整形的变量:
int main()
{
Apple a;
a.number = 10; // 一箱苹果有10个
}
我们也可以使用浮点数的变量:
int main()
{
Apple a;
a.weight_half_KG= 2.5; // 一箱苹果有2.5斤
}
获取联合成员的方式和获取结构成员的方式一。唯一的差异在于,当改变一个联合成员的值时,实际上修改了该联合所有成员的值。
int main()
{
Apple a;
a.weight_KG= 1.25; // 一箱苹果有1.25公斤
printf("%p\n", &a.number);
printf("%p\n", &a.weight_half_KG);
printf("%p\n", &a.weight_KG);
}
联合中的所有字段都可以访问,但它们会指向同一个地址。只是它们在使用时表现的数据类型不一样。
计算机需要保证联合的大小固定。唯一的办法就是使用最大的内存,让任何一个字段都装得下。如果定义的时候没有指定初始化,会被隐式地初始化为0值
联合提供了一种方法,一种可以用不同数据类型创建变量的方法。而且联合经常会和结构体一起使用。