6.4.3 指针的算术运算
指针不光可以移动,还可以进行算术运算。通过指针的算术运算,甚至可以达到多次指针移动的效果。
1.指针与整数的算术运算
可以将一个指针与整数值进行算术运算,运算的结果为一个新的指针,新指针所对应的内存地址为原内存地址+整数值*指针的数据类型大小。
假如有一个 int 类型的指针变量 pi,所存储的内存地址为 100。现在对它进行算术运算,表达式如下:
pi + 1
该表达式将指针变量 pi 与整数值 1 进行相加,这样会产生一个新的指针,新指针所对应的内存地址为 100 + 1 * 4,即 104,相当于指针向前移动一次的效果。
若表达式为:
pi + 2
该表达式将指针变量 pi 与整数值 2 进行相加,这样会产生一个新的指针,新指针所对应的内存地址为 100 + 2 * 4,即 108。相当于指针向前移动两次的效果。
需要注意的是,指针算术运算的结果会产生一个新的指针,即一个新的内存地址。它不会改变原指针变量所存储的内存地址,即指针变量 pi 的值并未改变。因此,可以对数组名进行算术运算。例如:
int *pi, a[5] = {10, 20, 30, 40, 50}; pi = a + 4;
第二条语句中,赋值运算符的右边是表达式“a + 4”,a 是数组名,可以看成指向数组首元素的指针,其与 4 相加,即相当于指针向前移动 4 次的效果,即得到了第 5 个数组元素的内存地址,并将其赋值给指针变量 pi。此时,指针变量 pi 就存储了第 5 个数组元素的内存地址,即拥有指向第 5 个数组元素的指针。
下面使用指针的算术运算实现例 6-1,代码如下:
在循环体中,只有一条 printf 函数调用语句,利用指针的算术运算分别得到指向不同数组元素的指针,并通过解引用访问到数组元素,将其打印到控制台窗口。需要注意的是,表达式“*(a + i)”中的小括号不要漏掉,否则表达式变成“*a + i”,即将数组首元素的值与变量 i 的值相加。
循环体一共被执行 5 次,下面是每一次循环中表达式“a + i”的结果:
(1)a + 0 的结果为 a 本身,即数组首元素的内存地址。
(2)a + 1 的结果为 a 的内存地址加上 4,即数组中第 2 个元素的内存地址。
(3)a + 2 的结果为 a 的内存地址加上 8,即数组中第 3 个元素的内存地址。
(4)a + 3 的结果为 a 的内存地址加上 12,即数组中第 4 个元素的内存地址。
(5)a + 4 的结果为 a 的内存地址加上 16,即数组中第 5 个元素的内存地址。
运行程序,结果如下:
10 20 30 40 50
从上面的结果可以看出,在访问数组元素时下标法与指针法的对应关系,例如要访问数组 a 中第 2 个元素时:
下标法:a[1]。
指针法:*(a + 1)。
2.指针与指针的算术运算
两个指针之间也可以进行算术运算,通常我们对指向同一数组中的元素的两个指针进行减法运算,来获得彼此之间的位置间隔信息。例如:
上面语句定义了两个 int 类型的指针变量,其中 p1 存储了首元素内存地址,p2 存储了第 5 个元素的内存地址。然后通过“p2 – p1”来进行两指针相减,需要注意的是,指针相减的结果并非简单的地址值相减,而是两指针所对应内存地址之间的差,再除以指针的数据类型大小的值,即:p2 存储的内存地址–p1 存储的内存地址
编译运行程序,结果如下:
The interval between the two array elements is 4.
可见,“p2 – p1”的结果为 4,即指针所指向的元素之间的位置间隔为 4,也就是 p2 所指向的数组元素位于 p1 所指向数组元素之后的第 4 个位置。
将代码中的表达式修改为“p1 – p2”:
int interval = p1 - p2;
重新编译运行程序,结果如下:
The interval between the two array elements is –4.
这次结果变成了–4,即表示 p1 所指向的数组元素位于 p2 所指向数组元素之前的第 4 个位置。
对于指针之间的算术运算,必须注意以下两点:
(1)两个指针所指向的必须是同一数组中的元素。
(2)不要对两个指针进行加、乘、除或求模等算术运算,这些都是无意义的行为。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论