联合
8 共用体
8.1 共用体的概念
有时需要使几种不同类型的变量存放到同一段内存单元中,也就是用覆盖技术,几个变量互相覆盖。这种几个不同的变量共占同一段内在的结构称为 共用体 类型的结构。
定义共用体类型的一般形式为
union 共用体名
{
成员表列
}变量表列;
例如:
union data
{
int i;
char ch;
float f;
}a, b, c;
也可以分开写
union data
{
int i;
char ch;
float f;
};
union data a, b, c;
即先声明一个 union data 类型,再将 a, b, c 定义为 union data 类型。当然也可以直接定义共用体变量如:
union
{
int i;
char ch;
float f;
}a, b, c;
可以看到 共用体 与 结构体 定义的形式相似,但它们的含义是不同的。
结构体变量所占内存长度是各成员占内存的和,每个成员分别占有自己的内存单元。
共用体变量所占的内存长度等于最长的成员的长度。例如,上面定义的 共用体 变量 a, b, c 各占 4 个字节,(因为一个实型变量占 4 个字节)而不是各占 2+1+4=7 个字节。
8.2 共用体变量的引用方式
只有先定义了共用体变量才能引用它,而且不能引用共用体变量,而只能引用共用体变量中的成员。例如,前面定义了 a, b, c 为共用体变量,下面的引用方式是正确的:
a.i;//引用共用体变量中的类型变量i
a.ch;//引用共用体变量中的字符变量ch
a.f;//引用共用体变量中的实型变量f
不能只引用共用体变量例如:
printf("%d", a);
是错误的,a 的存储区有好几种类型,仅写共用体变量名 a 难以使系统确定究竟输出的是哪一个成员的值。应该写成 printf("%d", a.i); 或 printf("%c", a.c); 等。
8.3 共用体类型数据的特点
在使用共用体类型数据时要注意以下一些特点:
(1)同一个内存段可以用来存放几种不同类型的成员,但每个瞬时只能存放其中一种,而不是同时存放几种,也就是说,第一瞬时只有一个成员起作用,其它的成员不起作用,即不是同时都存在和起作用。
(2)共用体变量中起作用的成员是最后一次存放的成员,在存入一个新的成员后原有成员就失去作用。如有以下的赋值语句:
a.i = 1;
a.c = 'a';
a.f = 1.5;
在完成以上3个赋值运算后,只有 a.f 是有效的,a.i 和 a.c 已经无意义了,此时用 printf("%d", a.i); 是不行的,而用 printf("%f", a.f); 是可以的,因为最后一次的赋值是向 a.f 赋值的,因此在引用共作体变量时要注意当前存放在共用体变量中的究竟是哪个成员。
(3)共用体变量的地址和它的各成员的地十都是同一个地址。例如:&a.i, &a, &a.c, &a.f 都是同一个地址。
(4)不能对共用体变量名赋值,也不能企图引用变量名来得到一个值,又不能在定义共用体变量时对它初始化。例如,下面这些都是不对的:
union
{
int i;
char ch;
float f;
}a={1, 'a', 1.5};
a = 1;
m = a'
(5)不能把共用体变量作为函数参数,也不能使函数返回共用体变量,但可以使用指向共用体变量的指针(与结构体变量这种用法相仿)。
(6)共用体类型可以出现在结构类型定义中,也可以定义共用体数组。反之,结构体也可以出现在共用体类型定义中。数组也可以作为共用体的成员。
如以下程序:
#include <stdio.h>
#include <stdlib.h>
struct
{
int num;
char name[10];
char sex;
char job;
union
{
int classes;
char position[10];
}category;
}person[2];
void main()
{
int n, i;
for(i=0;i<2;i++)
{
scanf("%d %s %c %c", &person[i].num, person[i].name, &person[i].sex, &person[i].job);
if(person[i].job == 's')
scanf("%d", &person[i].category.classes);
else if(person[i].job == 't')
scanf("%s", person[i].category.position);
else
printf("input error!");
}
printf("\n");
printf("NO. Name sex job class/position\n");
for(i=0;i<2;i++)
{
if(person[i].job == 's')
printf("%-6d %-10s %-3c %-3c %-6d\n", person[i].num, person[i].name, person[i].sex, person[i].job, person[i].category.classes);
else
printf("%-6d %-10s %-3c %-3c %-6s\n", person[i].num, person[i].name, person[i].sex, person[i].job, person[i].category.position);
}
system("pause");
}
运行结果如下:
101 Li f s 501
102 Wang m t professor
NO. Name sex job class/position
101 Li f s 501
102 Wang m t professor