是时候深入了解更多关于指针的新话题了!如果你对指针还不够熟悉,可以先查看本指南的第一部分。

11.1 Pointer Arithmetic

事实证明,你可以对指针进行算术操作,特别是加法和减法。

但这是什么意思呢?

简而言之,如果你有一个指向某种类型的指针,对指针加一,会让指针移动到内存中该类型的下一个元素的位置。

需要特别注意的是,当我们移动指针并查看内存中的不同位置时,一定要确保指针始终指向一个有效的内存地址,然后才能解引用。如果指针指向了无效的位置且尝试访问那里的内容,行为就是未定义的,程序崩溃是很常见的结果。

这和“数组/指针等价性”话题有点像先有鸡还是先有蛋的问题,但我们还是会尝试讲解一下。

11.1.1 Adding to Pointers

首先,我们取一个数字数组。

int a[5] = {11, 22, 33, 44, 55};

接着,获取指向数组第一个元素的指针:

int a[5] = {11, 22, 33, 44, 55};

int *p = &a[0];   // 或者写成 "int *p = a;" 也一样

然后,通过解引用指针来打印该位置的值:

printf("%d\\n", *p);   // 输出 1

现在使用指针运算,打印数组中下一个元素,即索引为1的元素:

printf("%d\\n", *(p + 1));   // 输出 22!!

发生了什么?C语言知道 p 是指向 int 类型的指针,所以它知道 int 的大小(例如 4 字节),并会跳过这么多字节,直接定位到紧接着第一个元素后的下一个 int

实际上,上述示例可以用下面两种等价的写法:

printf("%d\\n", *p);        // 输出 11
printf("%d\\n", *(p + 0));  // 输出 11

因为给指针加上 0 结果就是指向同一个地址的指针。