指针减法和比较规则混淆

  • 本文关键字:比较规则 指针 c
  • 更新时间 :
  • 英文 :


我在玩指针算术,在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("%pn",difference); Address exists
/*printf("%cn",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);
}

减去两个指针不会得到一个指针("address"),而是得到整数,即这些指针之间的"距离"。只有当指针都指向同一个数组时,这才有意义。同样,只有当指针在同一数组中时,比较指针才有意义。

当它没有意义时,结果是未定义的——这并不意味着程序将失败、崩溃或产生任何类型的错误。这意味着任何事情都可能发生,你没有权利抱怨。

您不能测试未定义的行为,因为结果是,呃,完全未定义的。

可能的结果包括获得预期结果、崩溃、获得意外结果或导致时间旅行。

在这种情况下,在普通台式计算机上,比较两个不相关的指针pointer_1>pointer_2的可能结果是比较存储在两个指针中的地址。所以它"有效"。

在具有分段存储器(如286)的计算机上,存储器地址由一对segment:offset组成。比较两个段值并不能说明哪一个代表最高的内存地址,因为它只是包含实际地址的段描述符表的索引。

因此,如果数组位于两个不同的段中(非常常见,因为段很小),那么比较指针的顺序没有多大意义,减去它们甚至都不起作用。

所以语言标准说你不能这样做,因为有时不起作用。

最新更新