常用指针运算
数据指针可以执行下面几种算数运算:
- 指针加上整数;
- 指针减去整数;
- 两个指针相减(不太容易理解);
- 比较指针。
引子
下面的计算结果应该为多少?想想再回答。
int a[5] = {1, 2, 3, 4, 5};
printf("value = %d\n", a-&a[4]);
指针加上整数
先看例子。
int vector[] = {28, 41, 7};
int *pi = vector; // pi: 100
printf("%d\n",*pi); // 显示28
pi += 1; // pi: 104
printf("%d\n",*pi); // 显示41
pi += 1; // pi: 108
printf("%d\n",*pi); // 显示7
从这个例子可以看到,对于整形数组,每次指针加1,地址就加4。【请特别理解这里提到的"指针加1"】。
其他类型的指针类型,要根据不同平台的区别,基本数据类型的长度不同,每次指针加1后,地址和基本类型长度是一致的。
指针减去整数
参考上面的例子,和加法类似,每次指针减1,地址就减4。
int vector[] = {28, 41, 7};
int *pi = vector + 2; // pi: 108
printf("%d\n",*pi); // 显示7
pi--; // pi: 104
printf("%d\n",*pi); // 显示41
pi--; // pi: 100
printf("%d\n",*pi); // 显示28
两个指针相减
理解了上面指针加上整数和指针减去整数后,我们再看两个指针相减的运算。先看例子。
int vector[] = {28, 41, 7};
int *p0 = vector;
int *p1 = vector+1;
int *p2 = vector+2;
printf("p2-p0: %d\n",p2-p0); // p2-p0: 2
printf("p2-p1: %d\n",p2-p1); // p2-p1: 1
printf("p0-p1: %d\n",p0-p1); // p0-p1: -1
通过例子我们可以看到,指针之间的差值是它们之间相差的“单位”个数,差的符号取决于操作数的顺序。这和指针加法是一样的,加到指针上的是数据的长度。我们把“单位”当做操作数。
在第一个printf语句中,我们看到数组的最后一个和第一个元素的位置相差2,就是说它们的索引值相差2。在最后一个printf语句中,差值是-1,表示p0在p1前面,而且它们紧挨着。
ptrdiff_t类型表示两个指针差值的可移植方式。在上例中,指针相减的结果以ptrdiff_t类型返回。因为指针长度可能不同,这个类型简化了处理差值的任务。
回答
回到开头的问题,对数组而言,a表示数组的首地址,a和 &a[0] 存储的都是数组首地址。&a[4] 这表示数组首第4个元素(元素的“单位”是int,一般默认是4个字节。)的地址。
因此开头的代码的打印数值应该为 -4 (相差4个“单位”。)