我正在玩指针,以便完全理解这个概念,然后想减去两个指针,期望这两个地址之间的距离或其他东西,但显然我错了,所以这是我的代码。
int x = 5, y = 7;
int *p = &y;
int *q = &x;
printf("p is %d\nq is %d\np - q is %d", p, q, (p - q));
为什么程序会输出
p - q is 1
?谢谢你。
这是未定义的行为。根据标准(
N1570
):
6.5.6 加法运算符
....
9 当两个指针相减时,两个都指向同一个数组对象的元素, 或者超过数组对象的最后一个元素;结果是 的差异 两个数组元素的下标。
请注意,如果允许,结果是 下标 差异。因此,如果指针指向同一类型的两个连续元素,则无论类型的大小如何,减法都会得到
1
。 (这也许就是您在具体案例中得到 1
的原因。)
您的特殊情况是导致未定义行为的原因,因为
p
和 q
指向不相关的对象。
仅当
p-q
和 p
指向同一个数组/超过同一数组的最后一个元素时,您才能理解 q
。
int array[10];
int* p = &array[0];
int* q = &array[5];
ptrdiff_t diff1 = q - p; // Valid. diff1 is 5
ptrdiff_t diff2 = p - q; // Valid. diff2 is -5
在本例中,q - p
为 5,因为它们指向数组中相距 5 个元素的元素。
换句话说,
p+5
等于q
。如果从 p
开始,跨过数组的 5 个元素,您将指向 q
所指向的数组中的同一个元素。
顺便说一句,不要使用格式说明符
%d
来打印指针。使用%p
。使用 %td
代替 ptrdiff_t
。
printf(" p is %p\n q is %p\n p-q is :%td", p, q, p-q);`
// ^^ ^^
请参阅 http://en.cppreference.com/w/c/io/fprintf 了解不同类型的有效格式说明符。
指针减法使用的公式是:
( p2 - p1 ) == ( addr( p2 ) - addr( p1 ) ) / sizeof( T )
T
是both
p1
和
p2
的类型。
int array[10];
int* p1 = array + 2;
int* p2 = array + 5;
int* a = p2 - p1; // == addr(array + 3)
int* b = p1 - p2; // == addr(array - 3)
//设a的地址为1000,则a+1的地址为1004
int a[]={1,2,3};
int *p1=a;
int *p2=a+1;
printf("%u",p2-p1);
结果将是 1 而不是 4。 在您的情况下,x 和 y 的位置是连续的,这就是 ans 的原因。是 1。
int a=5,b=6;
int *ptr=&a,*diff;
diff=ptr;
printf("%p\n",diff);
ptr++;ptr++;ptr++;ptr++;ptr++;ptr++;ptr++;ptr++;ptr++;ptr++;
printf("%p\n",ptr);
printf("diff==%td\n",(ptr-diff)*sizeof(int));
(diff-ptr) 将提供两个变量之间的距离,但不会提供两个指针之间的内存间隙。
重要提示:只有相同类型的指针才能相减。
设第一个元素的地址为1000,那么第二个元素
a+1
的地址将为1004。因此
p1 = 1000
和
p2 =1004
。
p2-p1 = (1004- 1000) /size of int = (1004-1000)/4 =4/4 =1