#include <stdio.h>
void main() {
int arr[] = {10,20,30,40};
int *p1 = arr;
int *p2 = &arr[2];
printf("%d",p2-p1);
}
输出:2
我很惊讶地看到输出为 2。我不知道为什么输出是 2。
int arr[] = {10,20,30,40};
arr | 10 | 20 | 30 | 40
index | 0 | 1 | 2 | 3
pointer | @+0 | @+1 | @+2 | @+3
int *p1 = arr;
int *p2 = &arr[2];
这意味着,p1 指向 arr 的首地址,即 @,p2 指向 arr 的第三个元素,即 @+2
printf("%d",p2-p1);
p2-p1 => @+2 - @ = 2 所以输出是2
当您从
p1
中减去 p2
时,即 (p2 - p1)
,您实质上是找到了它们内存地址之间的差异。由于两个指针都指向同一数组中的元素,因此它们的地址之间的差异表明它们在数组中相距多少个元素。所以,p2 - p1
给你2,表示有2个整数(或元素,因为int
,每个元素有4个字节)。
如果您想访问该值,可以通过
printf("%d",*p2-*p1);
来实现
在此声明中
int *p1 = arr;
数组指示符隐式转换为指向其第一个元素的指针。它相当于下面的声明
int *p1 = &arr[0];
像
arr[i]
这样的表达式,其中 i
是某个整数,其计算方式类似于 *( arr + i )
。也就是说,表达式 a[0]
的计算结果与 *( a + 0 )
相同,与 *( a )
或 *a
相同。表达式 a[2]
的计算方式与 *( a + 2 )
类似。对表达式应用运算符地址,您将得到p1
的值等于a + 0
或a
,并且p2
的值等于表达式a + 2
的值。
因此差值
p2 - p1
与 ( a + 2 ) - a
相同,等于 2
。
来自 C 标准(6.5.6 加法运算符)
8 当整数类型的表达式与指针相加或相减时,结果具有指针操作数的类型。如果指针操作数指向数组对象的元素,并且 数组足够大,结果指向原始元素的元素偏移量,使得结果数组元素和原始数组元素的下标之差等于整数表达式。 换句话说,如果表达式 P 指向数组对象的第 i 个元素,则表达式 (P)+N (等效于 N+(P))和 (P)-N (其中 N 的值为 n)分别指向第 i + n 个 和 i − 数组对象的第 n 个元素,前提是它们存在。 此外,如果表达式 P 指向数组对象的最后一个元素,则表达式 (P)+1 指向数组对象的最后一个元素之后的一个,如果表达式 Q 指向数组对象的最后一个元素,则表达式 (Q)-1 指向数组对象的最后一个元素。如果指针操作数和结果都指向 对于同一数组对象的元素,或者超过数组对象的最后一个元素,计算不应产生溢出;否则,行为是未定义的。如果结果指向过去 数组对象的最后一个元素,不得将其用作所计算的一元 * 运算符的操作数。
注意表达式的类型是
ptrdiff_t
。所以你应该写
printf("%td",p2-p1);
而不是
printf("%d",p2-p1);