减去两个指针,给出意想不到的结果
#include int main() { int *p = 100; int *q = 92; printf("%d\n", p - q); //prints 2 }
上述程序的输出不应该是8吗?
相反,我得到2。
除了未定义的行为,这是您使用指针算法获得的行为:当减去指针是合法的时,它们的差异表示指针之间的数据项的数量。 在int
情况下,在你的系统上每个int
使用四个字节,相隔八个字节的指针之间的差异是(8 / 4)
,这可以达到2
。
这是一个没有未定义行为的版本:
int data[10]; int *p = &data[2]; int *q = &data[0]; // The difference between two pointers computed as pointer difference ptrdiff_t pdiff = p - q; intptr_t ip = (intptr_t)((void*)p); intptr_t iq = (intptr_t)((void*)q); // The difference between two pointers computed as integer difference int idiff = ip - iq; printf("%td %d\n", pdiff, idiff);
演示。
这个
int *p = 100; int *q = 92;
已经无效C.在C中,您无法初始化具有任意整数值的指针。 除了从空指针常量0
转换之外,语言中没有隐式的整数到指针转换。 如果由于某种原因需要将特定的整数值强制转换为指针,则必须使用显式转换(例如int *p = (int *) 100;
)。
即使你的代码以某种方式编译,其行为也不是由C语言定义的,这意味着这里没有“应该”的答案。
您的代码是未定义的行为 。
你不能简单地减去两个“任意”指针。 引用C11
,章节§6.5.6/ P9
当减去两个指针时,两个指针都指向同一个数组对象的元素,或者指向数组对象的最后一个元素的元素; 结果是两个数组元素的下标的差异。 结果的大小是实现定义的,其类型(有符号整数类型)是在
头中定义的
ptrdiff_t
。 [….]
另外,如上所述,如果正确地减去两个指针,结果将是ptrdiff_t
类型,您应该使用%td
来打印结果。
那就是说,初始化
int *p = 100;
本身看起来很错!! 为了澄清,它不会将值100
存储到指向的内存位置( 问题:它指向哪里? ) p
。 它试图用整数值100
设置指针变量本身,这似乎是一个约束违反本身。
根据标准( N1570 )
当减去两个指针时,两个指针都指向同一个数组对象的元素,或者指向数组对象的最后一个元素的元素; 结果是两个数组元素的下标的差异。
这些是整数指针, sizeof(int)
是4.指针算术以指向的东西的大小为单位完成。 因此,以字节为单位的“原始”差异除以4.此外,结果是ptrdiff_t
因此%d
不太可能削减它。
但请注意,正如Sourav指出的那样,你所做的是技术上未定义的行为。 它几乎是偶然地在最常见的环境中工作。 但是,如果p和q指向同一个数组,则定义行为。
int a[100]; int *p = a + 23; int *q = a + 25; printf("0x%" PRIXPTR "\n", (uintptr_t)a); // some number printf("0x%" PRIXPTR "\n", (uintptr_t)p); // some number + 92 printf("0x%" PRIXPTR "\n", (uintptr_t)q); // some number + 100 printf("%ld\n", q - p); // 2
int main() { int *p = 100; int *q = 92; printf("%d\n", p - q); //prints 2 }
它被称为pointer arthmetic
那里发生了什么。
该值将为(100-92)/sizeof(int)
。 在你的情况下sizeof(int)=4
。
在ISO9899中,指针运算被定义为减法ptr-ptr
。 第6.5.6p9章
当减去两个指针时,两个指针都指向同一个数组对象的元素,或者指向数组对象的最后一个元素的元素; 结果是两个数组元素的下标的差异。