【问题标题】:Pointer Subtraction and Comparison Rule Confusion指针减法和比较规则混淆
【发布时间】: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


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

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

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

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-08-15
      • 1970-01-01
      • 1970-01-01
      • 2017-12-13
      • 2014-06-03
      • 2010-09-25
      • 2011-09-04
      相关资源
      最近更新 更多