结构也可以作为传递给函数的参数,它们也可以作为返回值从函数返回,相同类型的结构体变量相互之间可以赋值。
申明结构时使用另一种良好技巧是用typedef创建一种新的类型。
typedef struct{ int a; char b; float c; }Simple;
与
struct SIMPLE { int a; char b; float c; } ; struct SIMPLE x; struct SIMPLE y[20],*z;
区别:SIMPLE是一个结构标签,而Simple是类型名而不是个结构标签
所以类型名声明变量是这样:
Simple X; Simple y[20],*Z;
如果你想在多个源文件中使用同一种类型的结构,你应该把标签声明或者typedef形式的声明放在一个头文件中。当源文件需要这个声明时可以使用#include指令把那个头文件包含进来。
结构成员的直接访问
结构变量的成员是通过点操作符(.)访问的。
结构成员的间接访问、
struct COMPLEX *p p->f
结构的自引用
struct SELF_REF1{ int a; struct SELF_REF1 b; int c; };
这是非法的,最后导致重复下去永无止境。
struct SELF_REF2{ int a; struct SELF_REF2 *b; int c; };
这个声明和前面那个声明的区别在于b现在是一个指针而不是结构。编译器在结构的长度确定前就已经知道指针的长度,所以这种类型的自引用是合法的。
这种应用事实上所指向的是同一种类型的不同结构。更加高级的数据结构,如链表和树,都是用这种技巧实现的。每个结构指向链表的下一个元素或树的下一个分支。
警告警惕这个陷阱
typedef struct{ int a; SELF_REF3 *b; int c; }SELF_REF3;
这个声明的目的是为这个结构创建类型名SELF_REF3。但是,它失败了。类型名直到声明的末尾才定义,所以在结构声明的内部它尚未定义。
解决方案:用一个结构标签声明b
typedef struct SELF_REF3_TAG{ int a; struct SELF_REF3_TAG *b; int c; }SELF_REF3;
位段
位段的声明和任何普通的结构成员声明相同,但有两个例外。首先,位段成员必须声明位int.signed int
或unsigned int类型。其次,在成员名的后面是一个冒号和一个整数,这个整数指定该位段所占用的位的数目。
struct CHAR{ unsigned ch : 7; unsigned fomt :6; unsigned size :19; }; struct CHAR ch1;
联合的所有成员引用的是内存中的相同位置。
在一个成员长度不同的联合里,分配给联合的内存数量取决于它的最长成员的长度。
如果成员间的长度相差悬殊,当存储长度较短的成员时,会浪费的空间是相当可观的。此时,在联合中存储指向不同成员的指针而不是直接存储成员本身。解决了内存浪费的问题。
联合的初始化
联合变量可以被初始化,但这个初始值必须是联合第1个成员的类型,而且它必须位于一对花括号里面。