C++漫谈指针运算

首先我们先提出一个问题:指针为什么要有自己的类型?

前不久我也问过自己同样的问题,既然指针存储的是一个地址,即一串十六进制的数字,那他完全没必要有自己的类型,因为地址并不会有什么和数据类型有关的差异。那为什么还要有int类型指针,char类型指针这些呢,后来联想到指针运算才想明白这个问题。那么,什么是指针运算呢?

指针作为一个变量当然也可以进行运算,但是他的运算方式与普通运算不同,我们先来看一个例子:

#include <iostream>

int main(void)
{
    int a = 6;
    int *pointer = &a;
    std::cout << "地址1:" << pointer << std::endl;
    std::cout << "地址2:" << (pointer + 1) << std::endl;
    return 0;
}

运行这段代码查看输出结果,你会发现两个地址的差值是4个字节,正好是一个int类型占的字节数。这两者有什么联系吗?为什么不是一个字节而四个字节呢?是因为在指针运算中,编译器是根据指针的类型来进行加减运算,也就是说,加减的字节数将与指针的类型进行绑定。比如,如果我们把一个指向char类型的指针进行加一操作,地址的变化将会是一个字节,这正好就是一个char类型所占的字节数。

以int举例,指针的加减运算可以理解为:指针加1,就是下一个int类型变量的首地址;指针加2,就是下下一个int类型变量的首地址;指针减1,就是上一个int类型变量的首地址;指针减2,就是上上一个int类型变量的首地址;以此类推。是不是很好理解呢?

如果理解的话我们再来看一个例子:

#include <iostream>
using namespace std;

int main() {
	int m[5] = { 1, 2, 3, 4, 5 };
	int* p = m;
	for (int i = 0; i < 5; i++) {
		cout << *(p + i) << endl;
	}
}

如此一来我们就可以用指针来遍历一个数组,有一点要注意的是,这里的数组名m实际上是数组第一个元素的地址,即数组的首指针,因此我们才可以将他的值赋值给指针p,完成下面的指针运算。

我们再回到文章开头的那个问题,现在大家心里应该有了答案了吧。指针的类型使得所有数据类型的指针运算全部统一起来,无论是什么数据类型,指针+1都是指下一个元素的地址,这种特性使得我们在进行指针运算的时候没有必要再考虑这个数据类型占几个字节,大大简化了编写代码的过程,降低了错误率。

好了,本教程就到此结束啦,喜欢的小伙伴记得点赞哦,也欢迎志同道合的朋友们关注我和我一起交流。

2019年4月9日