预计阅读本页时间:-
喜欢使用指针的人会高兴地得知能够使用指向结构的指针。至少有三个原因可以解释为什么使用指向结构的指针是个好主意。第一,就像指向数组的指针比数组本身更容易操作(例如在一个排序问题中)一样,指向结构的指针通常都比结构本身更容易操作。第二,在一些早期的C实现中,结构不能作为参数被传递给函数,但指向结构的指针可以。第三,许多奇妙的数据表示都使用了包含指向其他结构的指针的结构。
下面的短例子(程序清单14.4)显示如何定义一个指向结构的指针及如何使用这个指针访问结构成员。
广告:个人专属 VPN,独立 IP,无限流量,多机房切换,还可以屏蔽广告和恶意软件,每月最低仅 5 美元
程序清单14.4 friends.c程序
请看输出结果:
我们先来看看怎样创建一个指向guy结构的指针,然后解释如何使用指针指定各个结构成员。
14.6.1 声明和初始化结构指针
声明很简单:
首先是关键字struct,其次是结构标记guy,然后是一个*号,紧跟着是指针名。这个语法和您见过的其他指针声明一样。
这个声明不是建立一个新的结构,而是意味着指针him现在可以指向任何现有的guy类型的结构。例如,如果barney是一个guy类型的结构,可以这样做:
和数组不同,一个结构的名字不是该结构的地址,必须使用&运算符。
在本例中,fellow是一个结构数组,就是说fellow[0]是一个结构,所以下列代码令him指向fellow[0],从而初始化了him:
头两行输出表明成功地执行了这个赋值语句。比较这两行输出,可以看出him指向fellow[0],him+1指向fellow[1]。注意him加上1,地址就加了 84。在十六进制中,ef8-ea4=54(十六进制)=84(十进制)。这是因为每个guy结构占有84字节的内存区域:names.first占20字节,names.last占20字节,favfood占20字节,job占20字节,income占4字节(即float在系统中的大小)。顺便提一下,在一些系统中,结构的大小有可能大于它内部各成员大小之和,那是因为系统对数据的对齐存储需求会导致缝隙。例如,系统有可能必须把每个偶数地址的成员放在是4的倍数的地址上,这样的结构就可能在其内部存在存储缝隙。
14.6.2 使用指针访问成员
指针him现在正指向结构fellow[0]。如何使用him来取得fellow[0]的一个成员的值呢?第三行输出展示了两种方法。
第一种方法,也是最常用的方法,是使用一个新运算符:->o这个运算符由一个连接号(-)后跟一个大于符号(>)组成。下面的例子可以清楚地表明这个意思:
换句话说,后跟->运算符的结构指针和后跟.(点)运算符的结构名是一样的(不能使用him.income,因为him不是一个结构名)。
务必要注意到him是个指针,而him->income是被指向的结构的一个成员。在这种情况下,him->income是一个float变量。
指定结构成员值的第二种方法从下面的序列中得出:如果him=&fellow[0],那么*him=fellow[0],因为&和*是一对互逆的运算符。因此,可做以下替代:
必须有圆括号,因为.运算符比*的优先级更高。
总之,如果him是指向名为barney的guy类型结构的指针,则下列表达式是等价的:
现在,我们来看看结构和函数的相互作用。