结构就是一种把一些数据项组合在一起的数据结构。其他编程语言把它称为记录 (record)。结构的语法很容易记忆:在C语言中,进行组合的通常方法就是把需要组合的东西 放在花括号里面:{内容〃}。关键字struct放在左花括号前面,以便编译器能够从程序块中认 出它:
struct {内容..• }
结构的内容可以是任何其他数据声明:单个数据项、数组、其他结构、指针等。我们可 以在结构的定义后面跟一呰变量名,表示这些变量的类型是这个结构。例如:
struct {内容...} plum, pomegranate, pear;
另外还需要注意的一点是,可以在struct关键字后面加一个可选的“结构标签”:
struct fruit一tag {内容...} plum, pomegranate, pear;
这样,我们就可以在将来的声明中用struct fruit」ag作为struct {内容...}的简写形式/。 因此,结构的通常形式是:
struct结构标签(可选){
类型1标识符1;
类型2标识符2;
类型N标识符N;
)变量定义(可选);
所以,在下面的声明中:
变量my_birthday、xmas、easter和groundhog_day属于相同的数据类型。结构中也允许 存在位段、无名字段以及字对齐所需的填充字段。这些都是通过在字段的声明后面加一个冒 号以及一个表示字段位长的整数来实现的。struct date_tag{ short dd, mm, yy; }my一birthday,xmas;
struct date—tag ea^ter, groundhog一day;
/*处理ID信息V
struct pid_tag {
unsigned int inactive : unsigned int : 1 ;
unsigned int re::count : unsigned int : 0;
short pid一id; struct pid—tag :rlink;
};
这种用法通常被称作“深入逻辑元件的编程”,你可以在系统编程中看到它们。它也能用 于把一个布尔标志以位而不是字符来表不。位段的类型必须是int, unsigned int或signed int(或 加上限定符)。至于int位段的值可不可以取负值则取决于编译器。
我不喜欢把结构的声明和变量的定义混合在一起。我更喜欢采用:
struct veg { int weight, price—per_lb; }; struct veg onion, radish, turnip;
而不是:
struct veg { i.nt v/^ight, price per lb; } onion, radish, turnip;
确实,后面一种方法可以少打了几个字,但我们应该更关心代码是否容易阅读,而不是 是否容易书写。我们只编写一次代码,但在以后的程序维护过程中将多次阅读这些代码。如 果一行代码只做一件事,看上去会更简单一些。基于这个理由,变量的声明应该与类型的声 明分开。
最后,还有两个跟结构有关的参数传递问题。有些C语言书籍声称“在调用函数时,参 数按照从右到左的次序压到椎栈里。”这种说法过于简单了——如果你有一本这样的书,把那 一页撕下烧掉。如果你有一个这样的编译器,把该编译器源代码的那几行删掉。参数在传递 时首先尽可能地存放到寄存器中(追求速度)。注意,im型变量i跟只包含一个im型成员 的结构变量s在参数传递时的方式可能完全不同。一个int型参数一般会被传递到寄存器中, 而结构参数则很可能被传递到堆栈中。第二点需要注意的是,在结构中放置数组,如:
/*数组位于结构内部*/
struct s_tag { int a[100]; };
现在,你可以把数组当作第一等级的类型.,用赋值语句拷贝整个数组,以传值调用的方 式把它传递到函数,或者把它作为函数的返回类型。
struct s_tag { int a [ 100]; };
struct s_tag orange, lime, lemon;
struct s_tag twofold(struct s—tag s) {
int j ;
for ( j ^ 0; j < 100; j++) s,a[j] *= 2; return s;
}
main() {
int i;
for(i = 0; i < 100; i++) lime.a[i] = 1;
lemon = twofold(1ime);
orange = lemon; /*给整个结构赋值*/
}
在典型情况下,并不会频繁地对整个数组进行赋值操作。但是如果需要这样做,可以通 过把它放入结构中来实现。让我们在本小节的最后,展示在结构中包含一个指向结构本身的 指针,这种方法常用于列表(list)、树(tree)以及许多其他动态数据结构。
/*结构内部有一个指向结构自身的指针*/
struct n〇de_tag{ int daturn;
struct node_tag *next;
In-struct node_tag a, b;
a.next = &b; /* a,b 链接在一起*/
a.next->next = NULL;