减去两个指针给出意想不到的结果

Subtracting two pointers giving unexpected result

#include <stdio.h>

int main() {
    int *p = 100;
    int *q = 92;
    printf("%d\n", p - q);  //prints 2
}

上面程序的输出不应该是8吗?

相反,我得到了 2。

您的密码是 undefined behavior.

您不能简单地减去两个 "arbitrary" 指针。引用 C11,章节 §6.5.6/P9

When two pointers are subtracted, both shall point to elements of the same array object, or one past the last element of the array object; the result is the difference of the subscripts of the two array elements. The size of the result is implementation-defined, and its type (a signed integer type) is ptrdiff_t defined in the <stddef.h> header. [....]

此外,如上所述,如果你正确地减去两个指针,结果将是 ptrdiff_t 类型,你应该使用 %td 来打印结果。


话虽如此,初始化

 int *p = 100;

看起来很不对劲!!澄清一下,它不会100的值存储到(问题:它指向哪里? ) p。它试图将指针变量本身设置为 100 的整数值,这本身似乎违反了约束。

撇开未定义的行为不谈,这就是您通过指针运算获得的行为:当减去指针合法时,它们的差表示指针之间的数据项数。如果 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);

Demo.

这个

int *p = 100;
int *q = 92;

已经是无效的 C。在 C 中,您不能用任意整数值初始化指针。除了空指针常量 0 的转换外,语言中没有隐式的整数到指针的转换。如果出于某种原因需要将特定整数值强制转换为指针,则必须使用显式转换(例如 int *p = (int *) 100;)。

即使您的代码以某种方式编译,它的行为也不是由 C 语言定义的,这意味着这里没有 "should be" 答案。

按照标准(N1570)

When two pointers are subtracted, both shall point to elements of the same array object, or one past the last element of the array object; the result is the difference of the subscripts of the two array elements.

这些是整数指针,sizeof(int)是4。指针运算是以所指事物的大小为单位进行的。因此 "raw" 字节差除以 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章

When two pointers are subtracted, both shall point to elements of the same array object, or one past the last element of the array object; the result is the difference of the subscripts of the two array elements.