6.4.2 指针的移动
在第 5 章中,我们是通过数组的下标来访问数组元素的。数组的下标从 0 开始,最后一个数组元素所对应的下标为数组长度减 1。通过循环,利用下标值不断自增,从而遍历数组所有元素。
通过指针的移动,我们也可以达到遍历数组所有元素的功能。因此,对于数组来说,我们既可以使用下标来访问数组元素,也可以使用指针来访问数组元素。我们将使用下标来访问数组元素的方式称为“下标法”;而将使用指针来访问数组元素的方式称为“指针法”。
指针的实质是内存地址,而内存地址是常量,它是不允许被修改的。而指针变量是用于存储内存地址的变量,它的值是可以被修改的。因此,所谓指针的移动,实质是对指针变量所存储的地址值进行修改的行为。我们可以通过对指针变量进行自增或自减的运算,来达到指针的移动效果。
指针的移动是有方向的,指针是从低内存地址向高内存地址的方向移动,称为指针的向前移动,是指针变量的自增运算行为。相反,指针是从高内存地址向低内存地址的方向移动,称为指针的向后移动,是指针变量的自减运算行为。
那指针每次移动的距离是多少?是不是每次移动 1 字节?
指针的移动距离和指针变量的类型相关,如果指针变量的类型为 char,则移动一次的距离为 1 字节;如果指针变量的类型为 short,则移动一次的距离为 2 字节;如果指针变量的类型为 int,则移动一次的距离为 4 字节。
假设这三个指针变量初始存储的内存地址都是 1:
char 类型的指针向前移动一次,它所存储的内存地址就会增加 1,变成 2。
short 类型的指针向前移动一次,它所存储的内存地址就会增加 2,变成 3。
int 类型的指针向前移动一次,它所存储的内存地址就会增加 4,变成 5,如图 6.12 所示。

图 6.12 不同类型指针的移动距离
【 例 6-1 】编写程序,通过指针的移动,遍历并打印数组所有元素。
代码如下:

在 for 循环之前,定义了指针变量 pi,并将数组首元素的内存地址作为其初始值。在循环体中共有两条语句,第 1 条语句以“[地址:值]”的格式来打印数组元素的内存地址和数组元素值;第二条语句,是对指针变量 pi 进行自增运算,这会导致指针的向前移动,每次移动的距离为 int 类型的大小,即 4 字节,也就是一个数组元素大小的距离。
编译运行程序,结果如下:
Addr: 2686660, Value: 10 Addr: 2686664, Value: 20 Addr: 2686668, Value: 30 Addr: 2686672, Value: 40 Addr: 2686676, Value: 50
可见,指针变量 pi 所存储的初始内存地址为 2686660,这就是数组首元素的内存地址。经过第一次向前移动后,指针变量 pi 所存储的内存地址增加了 4,变为了 2686664,即是第二个数组元素的内存地址;经过第二次向前移动后,指针变量 pi 所存储的内存地址又增加了 4,变为了 2686668,即第三个数组元素的内存地址;经过第三次向前移动后,指针变量 pi 所存储的内存地址又增加了 4,变为 2686672,即第四个数组元素的内存地址;经过第四次向前移动后,指针变量 pi 所存储的内存地址又增加了 4,变为了 2686676,即第五个数组元素的内存地址。那指针变量 pi 最终所存储的是第五个数组元素的内存地址吗?
for 循环的循环体一共会被执行 5 次,因此,指针的移动也将会进行 5 次。前面只讲了前 4 次,而指针第 5 次向前移动后,指针变量 pi 所存储的内存地址仍会增加 4,变为 2686680,不过这个地址已经超出了数组的范围,如果对其进行解引用的话就会造成数组的越界访问。不过此时 for 循环已经结束,所以并不会发生这种越界访问的行为。
最后再强调一下,由于“指针的移动”需要不断地修改指针变量所存储的地址值,因而不要使用数组名来进行指针的移动。数组名虽然是数组首元素的内存地址,也可以将其看成指向数组首元素的指针,但它不能被移动,即它的值不能被修改,必须一直存储首元素的内存地址。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论