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

时间:2017-10-23 14:23:32

标签: c pointers subtraction

#include <stdio.h>

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

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

相反,我得到了2.

6 个答案:

答案 0 :(得分:12)

除了未定义的行为,这是您使用指针算法获得的行为:当减去指针是合法的时,它们的差异表示指针之间的数据项数。如果int在您的系统上每个int使用四个字节,则八个字节间隔的指针之间的差异为(8 / 4),这可以达到2。< / p>

这是一个没有未定义行为的版本:

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.

答案 1 :(得分:2)

您的代码为undefined behavior

你不能简单地减去两个“任意”指针。引用C11,章节§6.5.6/ P9

  

当减去两个指针时,两个指针都指向同一个数组对象的元素,   或者超过数组对象的最后一个元素;结果是差异   两个数组元素的下标。结果的大小是实现定义的,   并且其类型(有符号整数类型)在ptrdiff_t标头中定义为<stddef.h>。 [....]

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

话虽如此,初始化

 int *p = 100;

本身看起来很错!!为了澄清,它将值100存储到指向的内存位置(问题:它指向哪里?p 。它试图用整数值100设置指针变量本身,这似乎是一个约束违规本身。

答案 2 :(得分:2)

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

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

即使你的代码以某种方式编译,它的行为也不是由C语言定义的,这意味着这里没有“应该”答案。

答案 3 :(得分:1)

根据标准(N1570

  

当减去两个指针时,两个指针都应指向   相同的数组对象,或者超过数组最后一个元素的数组   宾语;结果是两者下标的差异   数组元素。

答案 4 :(得分:0)

这些是整数指针,sizeof(int)是4.指针算术以指向的事物的大小为单位完成。因此&#34; raw&#34;差异以字节为单位除以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

答案 5 :(得分:0)

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章

  
    

当减去两个指针时,两个指针都指向同一个数组对象的元素,     或者超过数组对象的最后一个元素;结果是差异     两个数组元素的下标。