联合(union)是一个能在同一个存储空间里(但不同时)存储不同类型数据的数据类型。一个典型的应用是一种表,设计它是用来以某种即没有规律,事先也未知的顺序保存混合类型数据。使用联合类型的数组,可以创建相同大小单元的数组,每个单元都能存储多种类型的数据。
联合是以与结构相同的方式建立的,也是需要一个联合模板和一个联合变量。可以在一步中定义它们也可以使用联合标记在两步中定义。下面是一个带有标记的联合模板的例子:
union hold {
int digit;
double bigfl;
char letter;
};
具有类似声明的结构可以含有一个int类型数值和一个double类型数值以及一个char类型数值,而这个联合可以含有一个int类型数值或一个double类型数值或一个char类型数值。
下面是定义3个hold类型联合变量的例子:
union hold fit; //hold类型的联合变量
union hold save[10] //10个联合变量的数组
union hold *pu; //指向hold类型变量的指针
第一个声明创建一个变量fit。编译器分配足够的空间以保存所描述的可能性的最大需求。在这种情况下,列出的最大可能性是double型数据。在我们的系统里,它需要64位,即8个字节。第二个声明创建了一个save数组,它含有10个元素,每个元素大小为8个字节。第三个声明创建了一个指针,可以存放一个hold联合的地址。
可以初始化一个联合,因为联合只存放一个值 ,所以初始化的规则与结构的初始化不同。具体地,有3种选择:可以把一个联合初始化为同样类型的另一个联合;可以初始化联合的第一个元素;或者按C99标准,可以使用一个指定初始化项目。
union hold valA;
valA.letter='R';
union hold valB = valA; //把一个联合初始化为另一个联合
union hold valC = {88}; //初始化联合的digit成员(第1个元素)
union hold valD = {.bigfl = 118.2}; //指定初始化项目
下面示例了怎样使用联合:
fit.digit = 23; //把23存储在fit中,使用2个字节
fit.bigfl = 2.0; //清除23,存储2.0;使用8个字节
fit.letter = 'h'; //清除2.0存储'h';使用1个字节
点运算符表示正在使用哪种数据类型。在同一时间只能存储一个值。即使有足够的存储空间,也不能同时保存一个char类型和一个int类型。由您负责记住当前保存在联合中的数据的类型。
如同与指向结构的指针一起使用->运算符一样,可以与指向联合的指针一起使用->运算符:
pu = &fit;
x = pu->digit; //相当于 x = fit.digit
接下来显示了什么是不能做的:
fit.letter= 'A';
flnum = 3.02*fit.bigfl; //错误
这个语句序列是错误的,因为存储了一个char类型,而接下来的一行却假定fit的内容是double类型的。
但是,使用一个成员来将值保存到一个联合中,然后使用一个不同的成员来查看这些内容,这种做法有时会很有用。下一章的程序清单15.4就给出这样一个例子。
另一个可能会使用联合的地方是在某些结构中,该结构所存储的信息有赖于其中的一个成员。例如,假定有一个表示一辆汽车的结构。如果汽车归属于使用者,就要一个结构成员来描述这个所有者。如果汽车被租赁,需要一个成员来描述租赁它的公司。那么使用下面的语句行,可以做些事情 :
struct owner {
char socsecurity[12];
...
};
struct leasecompany{
char name[40];
char headpuarters[40];
...
};
union data {
struct owner owncar;
struct leasecompany leasecar;
};
struct car_data {
char make[15];
int status; /*0=私有,1=租赁*/
union data ownerinfo;
...
};
假定flits是一个car_data结构。那么如果flits.status是0,程序就可以使用fits.ownerinfo.owncar.socsecurity; 如果flits.status是1,程序就可以使用flits.ownerinfo.leasecar.name。
总结 :结构和联合运算符
成员运算符:
总体注解:
运算符和结构或联合名称一起使用,用来指定结构或联合的成员。如果name是一个结构名,member是一个由结构模板指定的成员,下面就表示了该结构的这个成员:
name.member
name.member的类型就是member的类型。成员运算符也可以用同样的方式用于联合。
间接成员运算符:
->
总体注解:
这个运算符与指向结构或联合的指针一起使用,用来指明结构或联合的成员 。假设ptrstr是一个指向结构的指针,member是由该结构模板指定的一个成员。那么:
ptrstr->member
这个表达式表示被指向结构的成员。间接运算符也可以用同样的方式用于联合。
例如:
struct {
int code;
float cost;
} item,*ptrst;
ptrst = &item;
ptrst->code=3451;
最后一条语句将一个int 值赋给item的成员code。以下三个表达式是等价的:
ptrst->code item.code (*ptrst).code