指针减法与比较规则混淆

时间:2017-11-08 19:55:22

标签: 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("%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);

}

2 个答案:

答案 0 :(得分:1)

减去两个指针不会产生指针(“地址”),它会产生整数,这是这些指针之间的“距离”。只有当指针指向同一个数组时才有意义。同样,比较指针只有在相同的数组中才有意义。

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

答案 1 :(得分:0)

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

可能的结果包括获得预期结果,崩溃,获得意外结果或causing time travel

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

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

因此,如果你的数组分为两个不同的段(非常常见,因为段很小),比较指令的顺序并没有多大意义,减去它们甚至不起作用。

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