在进行某些算法的C语言编程的时候,需要使几种不同类型的变量存放到同一段内存单元中。也就是使用覆盖技术,几个变量互相覆盖。这种几个不同的变量共同占用一段内存的结构,在C语言中,被称作“共用体”类型结构,简称共用体,也叫联合体。
—— 摘自百度百科
定义联合体与使用
联合体是一种特殊的数据类型,允许在相同的内存位置存储不同的数据类型。程序中可以定义带有多个成员的联合体,但是任何时候只能有一个成员带有值。共用体提供了一种使用相同的内存位置的有效方式。用到的关键字是 union,其格式如下:
union 联合体名称 {
member-list
}
实例代码如下:
#include<stdio.h>
union Person {
char name[50];
unsigned int age;
double weight;
};
int main() {
union Person person;
strcpy(person.name, "tom");
person.age = 27;
person.weight = 46.9;
printf("person.name = %s, person.age = %d, person.weight = %f\n", person.name, person.age, person.weight);
return 0;
}
执行结果:
person.name = 33333sG@諏鱱AQ, person.age = 858993459, person.weight = 46.900000
可以看到,只有成员 weight 的值是被正确的输出,原因是这三个成员变量在储值的时候占用的是同一个内存空间,相当于这三个成员指向的是同一块内存空间,当 weight 被赋值之后,其他的成员的值就被损坏。使用 &
可以查看各个成员指向的地址值:
union Person up;
printf("&up=%p, &up.name=%p, &up.age=%p, &up.weight=%p\n", &up, &up.name, &up.age, &up.weight);
执行结果如下:
&up=0022FF08, &up.name=0022FF08, &up.age=0022FF08, &up.weight=0022FF08
如果需要在联合体变量被声明的时候赋予初始值的话,因为它们共用同一个内存空间,故而,不需要将每个值都赋值,而且编译器只会接收第一个值作为有效值填入合适的成员中。例如:
#include<stdio.h>
union Person {
char name[50];
unsigned int age;
double weight;
};
int main() {
union Person up1 = {"Tom", 12, 4.6};
union Person up2 = {12};
union Person up3 = {4.6};
union Person up4 = {"Tom"};
printf("name=%s, age=%d, weight=%f\n", up1.name, up1.age, up1.weight);
printf("name=%s, age=%d, weight=%f\n", up2.name, up2.age, up2.weight);
printf("name=%s, age=%d, weight=%f\n", up3.name, up3.age, up3.weight);
printf("name=%s, age=%d, weight=%f\n", up4.name, up4.age, up4.weight);
return 0;
}
该源程序在编译的时候给出警告和提示:
warning: excess elements in union initializer
union Person up1 = {"Tom", 12, 4.6};
^~
note: (near initialization for 'up1')
warning: excess elements in union initializer
union Person up1 = {"Tom", 12, 4.6};
^~~
note: (near initialization for 'up1')
执行结果变成了:
name=Tom, age=7171924, weight=0.000000
name=, age=12, weight=0.000000
name=, age=4, weight=0.000000
name=Tom, age=7171924, weight=0.000000
从本例中可以看到,联合体 up1 和 up4 接受的值是字符串 Tom
,联合体 up2 接受的值是 12,联合体 up3 将传递的小数直接转换为了整型赋值给了 age 成员,接受的值是 4。故而,在给联合体变量声明的时候不需要为每个成员变量赋值,只需要赋予一个合适类型的值即可。
联合体作为参数
将联合体作为参数传递到函数中的操作方式与结构体一样。但是因为共享内存的原因,在函数内,仅接受一个有效值。代码如下:
#include<stdio.h>
#include<string.h>
union Person {
char name[50];
unsigned int age;
double weight;
};
void printPerson(union Person p) {
printf("Person{name:%s, age:%d, weight:%f}", p.name, p.age, p.weight);
}
int main() {
union Person up = {12};
printPerson(up);
return 0;
}
执行结果:
Person{name:, age:12, weight:0.000000}
指向联合体的指针
指向联合体的指针在使用上与结构体一致,主要使用的运算符是 ->
。具体代码如下:
#include<stdio.h>
#include<string.h>
union Person {
char name[50];
unsigned int age;
double weight;
};
void printPerson(union Person *p) {
printf("Person{name:%s, age:%d, weight:%f}", p->name, p->age, p->weight);
}
int main() {
union Person up = {12};
union Person *p = &up;
printPerson(p);
return 0;
}
执行结果:
Person{name:, age:12, weight:0.000000}