14.6 指向结构的指针
喜欢使用指针的人一定很高心使用指向结构的指针。至少有4个理由可以解释为何要使用指向结构的指针。第一,就像指向数组的指针比数组本身更容易操控(如,排序问题)一样,指向结构的指针通常比结构本身更容易操控。第二,在一些早期的C实现中,结构不能作为参数传递给函数,但是可以传递指向结构的指针;第三,即使能传递一个结构,传递指针通常更有效率。第四,一些用于表示数据的结构中包含指向其他结构的指针。
程序清单14.4 friends.c程序
/* friends.c -- uses pointer to a structure */
#include <stdio.h>
#define LEN 20
struct names {
char first[LEN];
char last[LEN];
};
struct guy {
struct names handle;
char favfood[LEN];
char job[LEN];
float income;
};
int main(void)
{
struct guy fellow[2] = {
{{ "Ewen", "Villard"},
"grilled salmon",
"personality coach",
68112.00
},
{{"Rodney", "Swillbelly"},
"tripe",
"tabloid editor",
432400.00
}
};
struct guy * him; /* here is a pointer to a structure */
printf("address #1: %p #2: %p\n", &fellow[0], &fellow[1]);
him = &fellow[0]; /* tell the pointer where to point */
printf("pointer #1: %p #2: %p\n", him, him + 1);
printf("him->income is $%.2f: (*him).income is $%.2f\n",
him->income, (*him).income);
him++; /* point to the next structure */
printf("him->favfood is %s: him->handle.last is %s\n",
him->favfood, him->handle.last);
return 0;
}
/* 输出:
*/
14.6.1 声明和初始化结构指针
声明结构指针很简单:
struct guy *him;
首先是关键字struct,其次是结构标记guy,然后是一个星号(*),其后跟着指针名。这个语法和其他指针声明一样。
该声明并未创建一个新的结构,但是指针him现在可以指向任意现有的guy类型的结构。
和数组不同,结构变量名不是结构变量的地址,因此要在结构变量名前面加上&运算符。
顺带一提,在有些系统中,一个结构的大小可能大于它各成员大小之和。这是因为系统对数据进行校准的过程中产生了一些“缝隙”。
14.6.2 用指针访问成员
如何通过him访问fellow[0]的成员的值?程序清单14.4中的第3行输出演示了两种方法。
第1种方法也是最常用的方法:使用->运算符。该运算符由一个连接号(-)后跟一个大于号(>)组成。
如果him == &barney,那么him->income 即是 barney.income
如果him == &fellow[0],那么him->income 即是 fellow[0].income
换句话说,指向结构的指针后面的->运算符和结构变量名后面的.运算符工作方式相同。
第2种方式是,以这样的顺序指定结构成员的值:如果him==&fellow[0],那么*him==fellow[0],因为*和&是一对互逆运算符。因此,可以做以下替代:
fellow[0].income == (*him).income
必须使用圆括号,因为.运算符比*运算符的优先级高。
总是,如果him是指向guy类型结构barney的指针,下面的关系恒成立:
barney.income == (*him).income == him->income //假设him == &barney