至少有三个原因可以解释为什么使用指向结构的指针是个好主意。
第一,就像指向数组的指针比数组本身更容易操作(例如在一个排序问题中)一样,指向结构的指针通常都比结构本身更容易操作。
第二,在一些早期的实现中,结构不能作为参数被传递给函数,但指向结构的指针可以。
第三,许多奇妙的数据表示都使用了包含指向其他结构的指针的结构。
下面的例子,示例了如何定义一个指向结构的指针,以及如何使用这个指针访问结构的成员;
程序清单14.4 friends.c程序
//friend.c --嵌套结构的例子#include#define LEN 20struct 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", 58112.00 }, { {"Rodney","Swillbelly"}, "tripe", "tabloid editor", 232400.00 } }; struct guy *him; //这是一个指向结构的指针 printf("address #1: %p #2: %p\n",&fellow[0],&fellow[1]); him=&fellow[0]; //告诉该指针它要指向的地址; 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++; /*指向下一个指针 */ printf("him->favfood is %s: him->handle.last is %s\n",him->favfood,him->handle.last); return 0;}
14.6.1 声明和初始化结构指针
声明很简单:
struct guy *him;
这个语法和您见过的其他指针声明一样。
这个声明不是建立 一个新的结构,而是意味着指针him现在可以指向任何现有的guy类型的结构。例如,如果barney是一个guy类型的结构,可以这样做:
him=&barney;
和数组不同,一个结构的名字不是该结构的地址,必须使用&运算符。
在本例中,fellow是一个结构数组,就是说fellow[0]是一个结构,所以下列代码令him指向fellow[0],从而初始化了him:
him=&fellow[0];
头两行输出表明成功地执行了这个赋值语句。比较这两行输出,可以看出him指向fellow[0],him+1指向fellow[1]。注意him+1,地址上就加了84。在十六进制 中,ef8-ea4=54(十六进制)=84(十进制)。这是因为每个guy结构占有84字节的内存区域:names.fiest占20字节,names.last占20字节,favfood占20字节,job占20字节,income占4字节(即float在系统中的大小)。顺便提一下,在一些系统中,结构的大小有可能大于它内部各成员大小的和,那是因为系统对数据的对齐存储需求会导致缝隙。例如,系统有可能必须 把每个偶数地址的成员放在是4的倍数的地址上,这样的结构就可能在其内部存在存储缝隙。
14.6.2 使用指针访问成员
指针him现在正指向结构fellow[0]。如何使用指针him来取得fello[0]的一个成员呢?第三行输出展示了两种方法。
第一种方法,也是最常用的方法,使用一个新的运算符:->。下面的例子可以清楚的表明这个意思 :
him->income is fellow[0].income if him==&fellow[0]
换句话说,后跟->运算符的结构指针和后跟(.)运算符的结构名是一样的(不能使用him.income,因为him不是一个结构名)。
务必要注意到him是个指针,而him->income是被指向的结构的一个成员。在这种情况下,him->income是一个float变量。
指定结构成员值的第二个方法从下面的序列中得出:如果him=&fellow[0],那么*him=fellow[0],因为&和*是一对互逆的运算符。因此,可做以下替代:
fellow[0].income==(*him).income
必须要使用圆括号,因为.运算符比*的优先级高。
总之,如果him是指向名为barney的guy类型结构的指针,则下列表达式是等价的:
barney.income=(*him).income=him->income //假设him=&barney