两个指针变量之间的差异
Difference between two pointer variables
我在笔试中问过这个问题。
运行 下面的代码在我的 lapi 上,我得到 10 作为输出
#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
。
您看到的是未定义的行为。
指针应该指向某个有效的内存位置,而 60 和 20 不是。
仅引用标准
两个指针都应指向同一数组对象的元素,或者指向数组对象最后一个元素的元素,因为这不是您在代码中看到的,这是 UB。
您正在评估两个指向 int
的指针之间的差异,或 "distance"。 sizeof(int)
在您的平台上是 4。 60 和 20 之间的差异是 40,这是 10 个 int 之间的距离。您的实施似乎只是在评估这种差异。
但是,C 标准对计算两个指针之间的差异进行了限制:两个指针都必须指向数组中的元素,或者指向数组末尾的元素。如果能保证i
和j
都满足这个,那么差值求值是有效的。由于您的代码不一定满足该条件,它可能有 未定义的行为,在这种情况下 output/outcome 可能是任何东西。
另请注意,取消引用 i
和 j
是未定义的行为,除非它们指向持有 int
值的有效地址。
根据 C 标准(6.5.6 加法运算符)
9 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
。因此,如果 sizeof( int )
等于 4
.
,则大小为 40 字节的内存可以容纳 10
个 int 类型的元素
这个值10是printf函数输出的
仅当两个指针都指向同一个(数组)对象(或后面的一个)时,C 标准才定义两个指针的不同,因此 OP 的代码调用未定义的行为。结果可以是任何东西。
来自 C11 标准:
6.5.6/9 Additive operators
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.
If the result is not representable in an object of that type, the behaviour is undefined.
以下代码有效:
#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
.
取不指向同一对象内部的指针之间的差异是未定义行为。
您的指针根本没有指向任何对象。
减去代码中的指针是未定义行为。
任何结果(10、40、65535、-1)都是错误的。
虽然它是严格的未定义行为并且允许发生任何事情,但是编译器在处理此类代码时很少会武断在这种情况下,结果可以解释为:
(i - j) == ((60 - 20) / sizeof(int))
但请注意,在某些情况下它可能不适用;例如,它可能取决于目标内存架构或对象的相对对齐方式。
我在笔试中问过这个问题。 运行 下面的代码在我的 lapi 上,我得到 10 作为输出
#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
。
您看到的是未定义的行为。
指针应该指向某个有效的内存位置,而 60 和 20 不是。
仅引用标准
两个指针都应指向同一数组对象的元素,或者指向数组对象最后一个元素的元素,因为这不是您在代码中看到的,这是 UB。
您正在评估两个指向 int
的指针之间的差异,或 "distance"。 sizeof(int)
在您的平台上是 4。 60 和 20 之间的差异是 40,这是 10 个 int 之间的距离。您的实施似乎只是在评估这种差异。
但是,C 标准对计算两个指针之间的差异进行了限制:两个指针都必须指向数组中的元素,或者指向数组末尾的元素。如果能保证i
和j
都满足这个,那么差值求值是有效的。由于您的代码不一定满足该条件,它可能有 未定义的行为,在这种情况下 output/outcome 可能是任何东西。
另请注意,取消引用 i
和 j
是未定义的行为,除非它们指向持有 int
值的有效地址。
根据 C 标准(6.5.6 加法运算符)
9 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
。因此,如果 sizeof( int )
等于 4
.
10
个 int 类型的元素
这个值10是printf函数输出的
仅当两个指针都指向同一个(数组)对象(或后面的一个)时,C 标准才定义两个指针的不同,因此 OP 的代码调用未定义的行为。结果可以是任何东西。
来自 C11 标准:
6.5.6/9 Additive operators
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. If the result is not representable in an object of that type, the behaviour is undefined.
以下代码有效:
#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
.
取不指向同一对象内部的指针之间的差异是未定义行为。
您的指针根本没有指向任何对象。
减去代码中的指针是未定义行为。
任何结果(10、40、65535、-1)都是错误的。
虽然它是严格的未定义行为并且允许发生任何事情,但是编译器在处理此类代码时很少会武断在这种情况下,结果可以解释为:
(i - j) == ((60 - 20) / sizeof(int))
但请注意,在某些情况下它可能不适用;例如,它可能取决于目标内存架构或对象的相对对齐方式。