6.1 结构的基本知识
我们首先来建立一些适用于图形领域的结构。点是最基本的对象,假定用x与y坐标表示它,且x、y的坐标值都为整数(参见图6-1)。
我们可以采用结构存放这两个坐标,其声明如下:
关键字struct引入结构声明。结构声明由包含在花括号内的一系列声明组成。关键字struct后面的名字是可选的,称为结构标记,(这里是point)。结构标记用于为结构命名在定义之后,结构标记就代表花括号内的声明,可以用它作为该声明的简写形式。
如果结构声明的后面不带变量表,则不需要为它分配存储空间,它仅仅描述了一个结构的模板或轮廓。但是,如果结构声明中带有标记,那么在以后定义结构实例时便可以使用该标记定义。例如,对于上面给出的结构声明point,语句
struct point pt;
定义了一个struct point类型的变量pt。结构的初始化可以在定义的后面使用初值表进行。初值表中同每个成员对应的初值必须是常量表达式,例如:
struct point maxpt = (320,200};
在表达式中,可以通过下列形式引用某个特定结构中的成员:
结构名.成员
其中的结构成员运算符“.”将结构名与成员名连接起来。例如,可用下列语句打印点pt的坐标:
printf(“%d,%x",pt.x,pt.y);
6.2 结构与函数
结构的合法操作只有几种:作为一个整体复制和赋值,通过&运算符取地址,访间其成员。其中,复制和赋值包括向函数传递参数以及从函数返回值。结构之间不可以进行比较。可以用一个常量成员值列表初始化结构,自动结构也可以通过赋值进行初始化。
如果传递给函数的结构很大,使用指针方式的效率通常比复制整个结构的效率要高。结构指针类似于普通变量指针。如声明
struct point *pp;
(*pp).x中的圆括号是必需的,因为结构成员运算符“.”的优先级比“*”的优先级高。表达式*pp.x的含义等价于*(pp.x),因为x不是指针,所以该表达式是非法的。
结构指针的使用频率非常高,为了使用方便,C语言提供了另一种简写方式。假定p是一个指向结构的指针,可以用
P->结构成员
这种形式引用相应的结构成员。
6.3 自引用结构
自引用结构是一个结构体,它包含对自身类型的指针。这种结构常用于创建链表、树等数据结构。
以下是一个简单的自引用结构的例子,用于创建一个单向链表:
在这个例子中,struct Node
是一个自引用结构,它包含一个指向相同类型的指针 next
。在 main
函数中,我们创建了三个节点并构建了一个链表。然后遍历并打印了链表中的值。
6.4 类型定义(typedef)
C语言提供了一个称为typedef的功能,它用来建立新的数据类型名,例如,声明
typedef int Length;
将Length定义为与int具有同等意义的名字。类型Length可用于类型声明、类型转换等,它和类型int完全相同,例如:
Length len,maxlen;
Length *lengths[];
注意,typedef中声明的类型在变量名的位置出现,而不是紧接在关键字typedef之后。这里必须强调的是,从任何意义上讲,typedef声明并没有创建一个新类型,它只是为某个已存在的类型增加了一个新的名称而已。typedef声明也没有增加任何新的语义:通过这种方式声明的变量与通过普通声明方式声明的变量具有完全相同的属性。实际上typedef类似于#define语句,但由于typedef是由编译器解释的,因此它的文本替换功能要超过预处理器的能力。
除了表达方式更简洁之外,使用typedef还有另外两个重要原因。首先,它可以使程序参数化,以提高程序的可移植性。如果typedef声明的数据类型同机器有关,那么,当程序移植到其他机器上时,只需改变typedef类型定义就可以了。一个经常用到的情况是,对于各种不同大小的整型值来说,都使用通过typedef定义的类型名,然后,分别为各个不同的宿主机选择一组合适的short、int和long类型大小即可。
typedef的第二个作用是为程序提供更好的说明性,更容易让人理解。
6.5 联合
联合是可以(在不同时刻)保存不同类型和长度的对象的变量,编译器负责跟踪对象的长度和对齐要求。联合提供了一种方式,以在单块存储区中管理不同类型的数据,而不需要在程序中嵌入任何同机器有关的信息。
联合的定义形式如下: