目录
11.8共用体/联合体
共用体的概念
有时需要使几种不同类型的变量存放到同一段内存单元中。例如,可以将一个整型变量、一个字符型变量、一个实型变量放在同一个地址开始的内存单元中(如下图)。以上3个变量在内存中占的字节数不同,但都从同一地址开始(图中设地址为1000)存放。也就是使用覆盖技术,几个变量互相覆盖。这种使几个不同的变量共占同一段内存的结构,称为“共用体”概念。
定义共用体类型变量的一般形式为:
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字节。
共用体变量的引用方式
只有先定义了共用体变量才能引用它,而且不能引用共用体变量,而只能引用共用体变量中的成员。例如,前面定义了a、b、c为共用变量,下面的引用方式是正确的。
a.i //引用共用体变量中的整型变量i
a.ch //引用共用体变量中的字符型变量ch
a.f //引用共用体变量中的实型变量f
不能只引用共用体变量,例如:
printf("%d",a); //是错误的
//正确写法
printf("%d",a.i);
printf("%c",a.ch);
a的存储区有好几种类型,分别占不同长度的存储区,仅写共用体变量名a,难以使系统确定究竟输出的是哪一个成员的值 。
共用体类型数据的特点
在使用共同体类型数据时要注意以下这些特点:
(1)同一个内存段可以用来存放几种不同类型的成员,但在每一瞬时只能存放其中一种,而不是同时存放几种。也就是说,每一瞬时只有一个成员起作用,其他成员不起作用,即不是同时都存在和起作用。
(2)共用体变量中起作用的成员是最后一次存放的成员,在存入一个新成员后原有的成员就失去作用。例如有以下赋值语句:
a.i = 1;
a.c = 'a';
a.f = 1.2;
//这个定义之后
printf("%d",a.i); //错误的
printf("%d",a.f); //正确的
在完成以上3个赋值运算后,只有a.f是有效的,a.i和a.c已经无意义了。因此在引用共同体变量时应十分注意当前存放在共用体变量中的究竟是哪个成员。
(3)共用体变量的地址和它各个成员的地址都是同一地址。例如&a、&a.i、&a.c、&a.f都是廷议地址值,其原因是显然的。
(4)不能对共用体变量名赋值,也不能企图引用变量名来得到一个值,又不能再定义共用体变量时对它初始化。例如,下面这些是不对的:
union {
int i;
char ch;
float f;
}a={1,'a',1.2}; //不能初始化
a = 1; //不能对共用体变量赋值
m = a; //不能引用共用体变量名以得到一个值
(5)不能把共用体变量作为函数参数,也不能使函数带回共用体变量,但可以使用指向共用体变量的指针(与结构体变量这种用法相仿)。
(6)共用体类型可以出现在结构体类型定义中,也可以定义共用体数组。反之,结构体也可以出现在共用体类型定义中,数组也可以作为共用体成员。
设有若干个人员的数据,其中有学生和教师。学生的数据包括:姓名、号码、性别、职业、班级。教师的数据包括:姓名、号码、性别、职业、职务。可以看出,学生和教师所含的数据是不相同的。现要求把它们放在同一表格中,如图。如果job项为s(学生),则第3项为class(班级)。即Li是501班的。如果job是t(教师),则第5项为position(职务)。Wang是prof(教授)。显然对第5项可以用共用体来处理(将class和position放在同一段内存中)。
要求输入人员的数据,然后输出。为简化起见,只设两个人(一个学生和一个教师)。
#include<stdio.h>
struct {
int num;
char name[10];
char sex;
char job;
union {
int banji;
char position[10];
}category;
}person[2];
int main()
{
for(int 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.banji);
}
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(int 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.banji);
}
else
{
printf("%-6d%-10s%-3c%-3c%-6s\n",person[i].num,person[i].name,person[i].sex,person[i].job,person[i].category.position);
}
}
return 0;
}
可以看到:在main函数之前定义了外部的结构体数组person,在结构体类型声明种中包括了共用体类型,category(分类)是结构体中一个成员名,在这个共用体中成员为class和position,前者为整型,后者为字符数组。
声明:本文章为个人学习笔记,资料整理参考谭浩强《C程序设计(第三版)》如有错误,欢迎大家指正!