什么是指针
C语言里,指针一直是一个难点,初学者容易混淆的地方,但是指针本身其实很简单,指针就是一个存放整数的变量。
C语言中,变量存放在内存中,而内存其实就是一组有序字节组成的数组,这些连续的字节从 0 开始进行编号,每个字节都有唯一的一个编号,这个编号就是内存地址。CPU 通过内存寻址对存储在内存中的某个指定数据对象的地址进行定位。这里,数据对象是指存储在内存中的一个指定数据类型的数值或字符串,它们都有一个自己的地址,而指针便是保存这个地址的变量。也就是说:指针是一种保存变量起始地址的变量。
如图为4GB 的内存的分布图:
什么叫做指向变量首地址呢?比如:
int a = 10;
int *p = &a;
用图表示就是:
为什么要使用指针
如果是写过类似Java、kotlin等高级语言的程序员,对引用肯定非常熟悉了,其实引用就是个简洁版的指针,因为指针实在太灵活,用得不好容易出事故,所以这些高级语言就简化为引用。
引用就像普通钥匙,我们可以用它去打开某种类型的门,其他类型数据无法打开,并且就算打开了门的具体编号(地址)也不会暴露给我们。引用不能通过移动位置(算数运算)去打开其他门,只能指定去打开某个门。
而指针虽然也有类型,但是却并不是要求一定要指向该类型的数据(至于指针的类型的作用后面会讲),指针有点像万能钥匙,虽然指定打开这某种门,但是其他门也是可以打开的(当然读取数据可能会有错误),更厉害的是可以移动任意位置(算术运算挪动指针指向)去打开其他门,门牌号(内存地址)也是暴露给我们的。这样会灵活很多,开发者的操作权限会很大,当然带来的风险也会高很多。
(上面的比喻可能不是很恰当或者难以理解,简单来说就是我可以使用指针直接操作内存,读也好,写也好,怎么样都好,内存的数据尽在我手中,内存的命运尽在我手中,我想读哪里的数据,我想往哪里写什么数据,都随我意。所以一旦操作不当,就会有程序事故,比如访问到没有访问权限的内存导致程序奔溃,比如常见的数组越界和野指针访问就是这个原因导致的奔溃)
总的来说,使用指针有如下好处:
1)指针的使用使得不同区域的代码可以轻易的共享内存数据,这样可以使程序更为快速高效;
2)C语言中一些复杂的数据结构往往需要使用指针来构建,如链表、二叉树等;
3)C语言是传值调用,而有些操作传值调用是无法完成的,如通过被调函数修改调用函数的对象,但是这种操作可以由指针来完成,而且并不违背传值调用。
4)可以通过算术运算灵活操作内存。
1和2比较容