#include<stdio.h>
int main()
{
int *i, *j;/* two pointer variable*/
i = (int *)60;
j = (int *)20;
printf("%d \n",i-j);
return 0;
}
输出:
10
任何人都可以告诉我为什么输出是10
。
答案 0 :(得分:9)
根据C标准(6.5.6添加剂操作员)
9当减去两个指针时,都指向元素 相同的数组对象,或者超过数组最后一个元素的数组 对象; 结果是两者下标的差异 数组元素。
因此,您的程序具有未定义的行为,因为指针不指向同一数组的元素。
Nevertheles似乎编译器只是生成一个用于减去两个指针的目标代码,而不管指针是否指向同一个数组的元素(它信任你)。
在这种情况下,根据指针算术的两个指针之间的差异是可以在两个指针之间放置在内存中的元素数。
在您的情况下,sizeof( int )
等于4
。因此,如果10
等于sizeof( int )
,则大小为40字节的内存可以容纳int类型的4
元素。
这个值为10的值由printf函数输出。
答案 1 :(得分:6)
您正在评估差异,或者&#34;距离&#34;在指向int
的两个指针之间。您的平台上sizeof(int)
为4。 60和20之间的差值是40,即10个英尺之间的距离。您的实现似乎只是评估这种差异。
但是,C标准限制了对两个指针之间差异的评估:两个指针都必须指向数组中的元素,或者指向一个结尾的元素。如果您可以确保i
和j
满足此要求,则差异评估有效。由于您的代码不一定满足该条件,因此它可能具有未定义的行为,在这种情况下,输出/结果可能是任何内容。
另请注意,取消引用i
和j
是未定义的行为,除非它们指向保留int
值的有效地址。
答案 2 :(得分:3)
只有当两个指针指向同一个(数组)对象(或后面一个)时,由C标准定义两个指针的差异,因此OP代码调用未定义的行为。结果可能是任何事情。
来自C11标准:
6.5.6 / 9加法运算符
当减去两个指针时,两个指针都指向同一个数组对象的元素, 或者超过数组对象的最后一个元素;结果是差异 两个数组元素的下标。结果的大小是实现定义的, 并且其类型(有符号整数类型)在
ptrdiff_t
标头中定义为<stddef.h>
。 如果结果在该类型的对象中无法表示,则行为未定义。
以下代码有效:
#include <stdio.h>
int main()
{
int a[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int * i = a + 0;
int * j = a + 10; /* Points "one past the last element" of the array. */
printf("%td \n", i - j);
return 0;
}
它还会打印10
。
答案 3 :(得分:2)
将未指向同一对象的指针之间的区别是Undefined Behavior。
您的指针根本不指向任何对象。
在代码中减去指针是未定义的行为。
任何结果(10,40,65535,-1)都是错误的。
答案 4 :(得分:1)
您所看到的是未定义的行为。
指针应指向某个有效的内存位置,而60和20则不是。
引用标准
两个指针都应指向同一个数组对象的元素,或者指向数组对象的最后一个元素之后的元素,因为这不是您在代码中看到的UB。
答案 5 :(得分:1)
虽然严格来说是未定义的行为并且允许发生任何事情,但编译器在处理此类代码时很少是任意的,结果可以在此解释案例:
(i - j) == ((60 - 20) / sizeof(int))
但请注意,在某些情况下可能不适用;例如,它可能取决于目标存储器架构或对象的相对对齐。