结构和联合
结构体基础
聚合类型
聚合类型:能够同时存储超过一个单独的数据,C语言提供两种聚合数据类型数组和结构。
数组和结构的区别:
- 数组是相同类型的数据的聚合,结构是不同类型数据的聚合。
- 因为数组的元素长度相同可以采用下标方式访问,结构成员的长度不同,只能通过名字访问,不能通过下标来访问。
- 数组名在表达式中使用时被当做一个指针,而结构体变量在表达式中使用时不能被当做一个指针。
结构体的声明
结构的通常形式
struct tag(可选) { member-list }variable-list(可选);
基于以上形式,结构可以有如下几种声明:
//形式1 struct { int age; char name[10]; } Person1, Person2; //形式2 struct PersonT { int age; char name[10]; } Person1; struct PersonT Person2; //形式3 struct PersonT { int age; char name[10]; }; struct PersonT Person1, Person2;
- 在形式2和形式3种,使用结构标签可以在将来的声明中用struct tag 作为struct {内容...}的简写形式。
- 在第2种形式中,结构的声明和变量的定义混合在一起,使得代码可能不易阅读。
- 将结构的声明和变量的定义分开来写是一个更好的选择,如第3种形式所示。
注意:
struct { int a; char b; float c; }x; struct { int a; char b; float c; }*y;
第一个声明创建了一个x变量,它包含了三个成员,一个整数,一个字符和一个浮点数。
第二个声明创建了指向一个结构类型的指针。
需要注意的是虽然两者结构体的成员是一致的,但是编译器将它们认为是不同的变量类型,所以下面的表达式是不合法的:
y = &x
typedef 创建新的结构类型
声明结构时可以使用的另一种良好技巧是用typedef创建一种新的类型,如:
typedef struct { int age; char name[10]; }PersonT; PersonT Person1, Person2;
此时,PersonT 是一种typedef定义的新的类型,而不再是结构标签。
注意:
struct { }NewVarT; typedef struct { }NewTypeT;
二者表达的意思截然不同。前者声明了一个结构变量,而后者则声明了一种新的类型。
结构的成员
间接访问与直接访问
struct PersonT { int age; char name[10]; }; struct PersonT Person1; struct PersonT *pPerson;
直接访问
Person1.age; Person1.name[0]; //.和[]的优先级相同,结合顺序为从左到右,因此可以省略括号
间接访问
pPerson->age; pPerson->name[0]; //->和[]的优先级也相同
结构的自引用
结构的成员变量的类型不能是结构本身,但可以是指向自身结构的指针类型。例如:
struct SelfT { int a; struct SelfT b; } struct SelfT { int a; struct SelfT *b; }
前者是非法的,结构体中包含自己的成员,这样一直重复永无止境。
而后者则是合法的。实际上,更加高级的数据结构,如链表和树,都是用这种技巧实现的。