【发布时间】:2017-11-08 19:55:22
【问题描述】:
我在玩指针算术,遇到了 C 标准中关于指针减法和比较的两条规则。
规则 1:当两个指针相减时,两个指针都必须指向同一个数组对象的元素,或者仅指向数组对象最后一个元素的一个元素(C 标准,6.5.6);结果是两个数组元素的下标之差。否则,操作是未定义的行为 (48)。
规则 2:类似地,使用关系运算符 = 和 > 比较指针会给出指针相对于彼此的位置。不指向同一个聚合或联合(也不只是超出同一个数组对象)的指针使用关系运算符(6.5.8)进行比较。否则,操作是未定义的行为 (53)。
减去或比较不引用同一数组的指针是未定义的行为。
问题 1:根据上面提到的规则 1,行为是未定义的,但程序确实打印了一个地址作为输出。当我尝试取消引用包含地址的变量时程序崩溃。怎么有一个地址存在,但地址指向的值不存在?
问题2:根据上面提到的规则2,使用关系运算符比较引用两个不同数组的两个指针是未定义的行为,程序应该崩溃,但我最终得到一个输出?这怎么可能?
有人可以帮我解决这个规则混乱吗?我已经发布了下面的代码:
#include <stdio.h>
int main()
{
char *pointer_1;
char *pointer_2;
char *difference;
int counter=0;
char string[20]={"Pointer Arithmetic"};
char str[30]={"Substraction and Comparison"};
pointer_1=string;
pointer_2=str;
difference=(char *)(pointer_2-pointer_1);
printf("%p\n",difference); Address exists
/*printf("%c\n",difference);*/ Dereferencing leads to program crash
while(pointer_1>pointer_2) Is one is allowed to use relational operators on
pointers which point to two different arrays?
{
{
counter++;
pointer_2++;
}
}
printf("%d",counter);
}
【问题讨论】:
-
未定义的行为!= 需要崩溃。它可以做任何事情,包括“正常”工作。
-
减去指针结果为
int。所以difference=(char *)(pointer_2-pointer_1);没有意义。 -
两个地址的区别本身并不是一个地址。正如明确指出的,它是“下标的差异”。使用 %p 也不能使其成为一体,printf 没有义务使您的程序崩溃。
-
@ConstantineGeorgiou 其实是
ptrdiff_t,它的签名类型不一定是int。 -
如果地址在类型大小的模上相等,则公共数组之外的两个指针之间的差异只是一个整数。否则没有整数结果是明智的。事实上,优化编译器通常利用这种要求来计算差异,使用快速模逆(读取:乘法)而不是除以类型大小,可能会产生与可能预期的舍入整数结果完全不同的结果。
标签: c