有时需要使几种不同类型的变量存放到同一段内存单元中。例如,可把一个整型变量、一个字符型变量、一个双精度型变量放在同一个地址开始的内存单元中(见图7.12)。
以上3个变量在内存中占的字节数不同,但都从同一地址开始存放。也就是使用覆盖技术,几个变量互相覆盖。这种使几个不同的变量共占同一段内存的结构,称为共用体(union )类型的结构(有些书译为联合)。
声明共用体类型的一般形式为:
union 共用体类型名{成员表列};
定义共用体变量的一般形式为:
共用体类型名 共用体变量名;
当然也可在声明共用体类型的同时定义共用体变量,也可没有共用体类型名而直接定义共用体变量。例如可以看到,“共用体”与“结构体”的定义形式相似。但它们的含义是不同的。结构体变量所占内存长度是各成员占的内存长度之和。每个成员分别占有其自己的内存单元。共用体变量所占的内存长度等于最长的成员的长度。
不能引用共用体变量,而只能引用共用体变量中的成员。例如,下面的引用方式是正确的:
a.i (引用共用体变量中的整型成员i)
a.ch (引用共用体变量中的字符型成员ch)
a.f (引用共用体变量中的双精度型成员d)
不能只引用共用体变量,例如
cout<<a;
是错误的,应该写成
cout<<a.i;
或
cout<<a.ch;
等。
【例7.7】设有若干个人员的数据,其中有学生和教师。学生的数据中包括: 姓名、号码、性别、职业、年级。教师的数据包括: 姓名、号码、性别、职业、职务。可以看出,学生和教师所包含的数据是不同的。
现要求把它们放在同一表格中,如果job项为s(学生),则第5项为grade(年级)。即Li是3年级的。如果job项是t(教师),则第5项为position(职务)。Wang是prof(教授)。显然对第5项可以用共用体来处理(将class和position放在同一段内存中)。要求输入人员的数据,然后再输出。为简化起见,只设两个人(一个学生、一个教师)。
程序如下:
#include <iostream>
#include <string>
#include <iomanip>//因为在输出流中使用了控制符setw
using namespace std;
struct
{
int num;
char name[10];
char sex;
char job;
union P //声明共用体类型
{
int grade; //年级
char position[10]; //职务
}category; //成员category 为共用体变量
}person[2]; //定义共用体数组person,含两个元素
int main( )
{
int i;
for(i=0;i<2;i++) //输入两个学生的数据
{
cin>>person[i].num>>person[i].name
>>person[i].sex>>person[i].job;
if(person[i].job=='s')
cin>>person[i].category.grade; //若是学生则输入年级
else
if (person[i].job=='t')
cin>>person[i].category.position; //若是教师则输入职务
}
cout<<endl<<"No. Name sex job grade/position"<<endl;
for(i=0;i<2;i++)
{
if (person[i].job=='s') cout<<person[i].num<<setw(6)
<<person[i].name<<" "<<person[i].sex <<" "
<<person[i].job<<setw(10)<<person[i].category.grade<<endl;
else cout<<person[i].num<<setw(6)<<person[i].name
<<" "<<person[i].sex <<" "<<person[i].job
<<setw(10)<<person[i].category.position<<endl;
}
return 0;
}
运行情况如下:
为了使输出结果上下对齐,在cout语句中用了setw控制符和插入空格。往往需要试验多次。