遇到一道题,问:两个指针变量可不可以相减?
答案是:可以
以前只写过 “指针±整数”,比如数组方面的,两个指针的运算还是第一次碰。
《C和指针》里说:
只有当两个指针都指向同一个数组中的元素时,才允许从一个指针减去另一个指针。
两个指针相减的结果的类型是
ptrdiff_t
,它是一种有符号整数类型。减法运算的值是两个指针在内存中的距离(以数组元素的长度为单位,而不是以字节为单位),因为减法运算的结果将除以数组元素类型的长度。例如,如果p1指向array[i],而p2指向array[j],那么p2-p1的值就是j-i的值。
假定数组元素的类型为float,每个元素占4个字节的内存空间。如果数组的起始位置为1000,p1的值是1004,p2的值是1024,但表达式p2-p1的结果将是5,因为两个指针的差值(20)将除以每个元素的长度(4)。
如果两个指针所指向的不是同一个数组中的元素,那么他们之间相减的结果是未定义的。就像如果你把两个位于不同街道的房子的门牌号码相减,不可能得到 这两所房子间的房子数一样。程序员无从知道两个数组在内存中的相对位置,如果不知道这一点,两个指针之间的距离就毫无意义
其实,指针相减的条件不一定非得指向同一个数组中的元素,可能是编译器的原因,下面这段代码可以更好得看清两个指针相减的情况。
#include <stdio.h>
int main()
{
int a = 10000; //整型变量a
char c = 't'; //字符型变量c
int *p1 = &a; //整型指针p1指向a
char *p2 = &c; //字符型指针p2指向c
ptrdiff_t num1 = p2 - p1; //ptrdiff_t型变量num1
int num2 = p1 - p2; //int变量num2,ptrdiff_t也是有符号整型,用两个类型声明变量来观察两者的异同
printf("&a= %d\n", &a);
printf("&c= %d\n", &c);
printf("p1= %x\n", p1);
printf("p2= %x\n", p2);
printf("num1=%d, num2=%d\n", num1, num2);
}
VS2017运行结果:
每次运行时,变量a、c的地址常常会变,但它们的差值,也就是num1、num2的值不变。
比如这次运行时,a的地址p1是9632172,c的地址p2是9632163。
p2-p1的值是-9,正好是两个地址相差9个字节
p1-p2的值是2,结果应该是9,但是被减数p1指向的变量a是int型,占4个字节,9除以4取整等于2。
同理,p2-p1时,p2指向的变量c是字符型,占1个字节,-9除以1取整等于-9.
但是指针的加、乘、除编译都不通过。