减去两个指针给出意想不到的结果
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);
这个
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.
#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);
这个
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.