13.3.4 关于结构的补充细节

这里应该提到定义结构时有一些灵活性。首先,将变量定义为特定结构类型的同时,声明这个结构是合法的。只需要将变量名称放在结构定义的终止分号之前即可。比如,表达式


struct date

{

int month;

int day;

int year;

}todaysDate, purchaseDate;


定义了date结构,同时也声明了变量todaysDate和purchaseDate为这个类型。还可以按常规方式来给变量赋初值。因此


struct date

{

int month;

int day;

int year;

}todaysDate={9,25,2010};


定义了date结构,同时也将变量todaysDate赋予如上初值。

如果定义结构时,也定义了该结构类型的所有变量,那么可以省略结构名称。所以表达式


struct

{

int month;

int day;

int year;

}dates[100];


定义了包含100个元素的数组dates。每个元素都是包含月、日和年三个整型成员的结构。因为</p>

没有为这个结构提供名称,所以定义同类型变量的唯一方式就是再次显式地定义这个结构。

位字段

在Objective-C语言中有两种包装信息的方式。一种方式是在整数内表示这些数据,然后使用第4章“数据类型和表达式”中提到的位运算符来访问所需的位。

另一种方式是用Objective-C语言所谓的位字段(bit field)来定义包装信息的结构。这种方法在定义结构时用到了特殊语法,它允许定义一个位字段并给该字段指定名称。

要定义位字段,可以定义一个名为packedStruct的结构,比如:


struct packedStruct

{

unsigned int f1:1;

unsigned int f2:1;

unsigned int f3:1;

unsigned int type:4;

unsigned int index:9;

};


结构packedStruct定义为包含5个成员。第一个成员名为f1,是unsigned int。成员名称之后的:1表示这个成员将占用1位。类似地,标志f2和f3定义为1位。成员type被定义占用4位,而成员index定义为9位。

编译器自动地将前面的位字段定义包装在一起。这种方式好的方面是定义为packedStruct类型的字段变量可以和一般结构成员那样进行访问。所以,如果如下声明一个名为packedData的变量:


struct packedStruct packedData;


那么,可以使用这个简单的表达式方便地将packedData中的type字段设置为7:


packedData.type=7;


还可以使用类似的表达式将该字段赋值为n:


packedData.type=n;


后面这种情况,不必考虑n的值对于type字段是否过大,只有n的低4位赋值给packedData.type。

从位字段中提取数值同样也是自动执行的,所以语句


n=packedData.type;


提取packedData的type字段(自动根据需要将它移到低位)并将之赋给n。

位字段可以用在正则表达式中,并且自动转换成整型数据。因此语句


i=packedData.index/5+1;


是完全合法的,下面的表达式也一样:


if(packedData.f2)

……


这个语句测试标志f2是开还是关。关于位字段值得注意的一个事项是:不能保证字段在内部赋值时是从左到右还是从右到左。因此,如果位字段是从右向左赋值,那么f1将位于最低位,f2位于f1左边的位置,依此类推。除非处理由不同程序或其他机器产生的数据,否则这并不会产生问题。

还可以在包含位字段的结构中包含正常的数据类型。因此,如果想要定义包含一个int、一个char和两个1位标志的结构,下面的定义是合法的:


struct table_entry

{

int count;

char c;

unsigned int f1:1;

unsigned int f2:1;

};


位字段在结构定义中被包装成单位(units),单位的大小由实现来定义,并且最可能是一个字大小。Objective-C编译器并不会因为尝试优化存储空间,而重新组织位字段定义。

可以指定没有名称的位字段来跳过字中的某些位,比如下面的语句


struct x_entry

{

unsigned int type:4;

unsigned int:3;

unsigned int count:9;

};


定义了一个x_entry结构,它包含一个名为type的4位字段和一个名为count的9位字段。未命名的字段表示分开type和count字段的3个位。

字段规范的最后一点涉及到长度为0的未命名字段这一特殊情况。它可以用来强制调整结构中的下一个字段作为单位边界的开始点。