13.5 联合

在Objective-C编程语言中,最不寻常的构造之一就是联合(union)。这种结构主要用在需要在相同存储区域存放不同类型数据的更高级编程应用中。比如,如果要定义一个名为x的变量,它可以用来存储单个字符、一个浮点数或是一个整数,那么首先要定义一个联合,可能名为mixed,如下所示:


union mixed

{

char c;

float f;

int i;

};


联合的声明和结构的声明一样,除了关键字用的是union而不是结构声明中所用的struct。联合和结构的真正区别在于,联合必须涉及到内存的分配方式。如下语句


union mixed x;


声明一个union mixed类型的变量,它并没有定义x包含三个不同成员c、f和i;而是定义x为包含有成员c、f、i其中之一。这样,变量x可以用来存储char型、float型或int型的数据,但不是同时存储这三个数据(也不是存储其中两个数据)。可以使用如下表达式将一个字符存储到变量x中:


x.c=‘K’;


要将一个浮点数存储到x中,可以使用符号x.f:


x.f=786.3869;


最后,要将整数count除以2的结果存储到x中,使用如下语句:


x.i=count/2;


因为x的float、char和int成员共存于内存中的同一位置,所以每次只能有一个数值存入x。此外,必须确保从联合获得的值与联合中最后存入的类型一致。

定义联合时,并不要求有联合名称,而且在声明联合的同时可以定义联合变量。也可以声明联合的指针,它们执行运算的的语法和规则与结构的相同。最后,可以如下初始化联合变量:


union mixed x={‘#’};


该语句将x的第一个成员(即c)设置为字符#。还可以通过名称初始化特定成员,如下所示:


union mixed x={.f=123.4;};


还可以将自动联合变量初始化为同类型的另一个联合变量。

使用联合允许你定义一个存储不同数据类型元素的数组。比如,语句


struct

{

char*name;

int type;

union

{

int i;

float f;

char c;

}data;

}table[kTableEntries];


设置了一个包含kTableEntries元素的数组table。数组中的每个元素都包含一个结构,它包含一个名为name的字符指针、一个名为type的整型数和一个名为data的联合成员。数组中的每个data成员可以存储一个int型、float型或char型数据。整数成员type也许用来记录存储在成员data中的数据类型。例如:如果data中存储的是int型数据,可以将它赋值为INTEGER(假设已经适当地定义了);如果存储的是float型数据,可以赋值为FLOATING;如果存储的是char型数据,则赋值为CHARACTER。通过这个信息可以知道如何应用特定数组元素中的特定data成员。

要将字符‘#’存入table[5],并且随后设置type字段,以说明该位置存储的是字符,可以使用下面两条语句:


table[5].data.c=‘#’;

table[5].type=CHARACTER;


依次访问table中的元素时,通过编写合适的测试语句序列,可以确定每个元素中存储的data值类型。比如,下面的循环将在终端显示每个名称及table中相关的值:


enum symbolType{INTEGER, FLOATING, CHARACTER};

……

for(j=0;j<kTableEntries;++j)

{

NSLog(@“s”,table[j].name);

switch(table[j].type)

{

case INTEGER:

NSLog(@“i”,table[j].data.i);

break;

case FLOATING:

NSLog(@“g”,table[j].data.f);

break;

case CHARACTER:

NSLog(@“c”,table[j].data.c);

break;

default:

NSLog(@“Unknown type(%i),element%i”,

table[j].type, j);

break;

}

}


前面说明的应用类型对于存储符号表可能很实用,它可能包含每个符号的名称、类型和值(也许还有该符号的其他信息)。