超出范围指针的未定义行为的标准中的歧义

时间:2015-05-21 09:11:37

标签: c++ c++11 language-lawyer semantics undefined-behavior

ISO IEC14882-2011§5.7/ 5 国家:

  

如果指针操作数和结果都指向同一个数组对象的元素,或者指向数组对象的最后一个元素,则评估不应产生溢出;否则,行为未定义。

此部分在此处不时用于stackoverflow。例如,争论为什么指向nullptr的指针的增量为UB,如here。然后将其解释为具有不指向数组对象的元素的指针。是未定义的行为。

然而,当我读到这篇文章时,我理解它指的是指针是UB的评估。这意味着拥有这样的指针是明确定义的行为。当一个人试图取消引用它时,行为就变得不确定了。

这意味着,例如,将有效指针递增到数组边界之外是合法的。之后再次减少是合法的。并且由于指针将与增量之前的值相同,因此评估也是合法的。

两者中哪一个是这样的?

3 个答案:

答案 0 :(得分:4)

您引用的段落是指针运算,而不是指针的评估。

它声明指定添加p + i的唯一时间是否为 (将i减法等同于-i

的加法
  1. p指向数组对象的元素或指向最后一个元素的元素,
  2. p + i指向同一个数组对象的元素,或者指向最后一个元素的元素
  3. 如果p 不是指向数组元素的指针或“一个超过结尾” - 例如,如果它是空指针或“两个结束” - 行为未定义。
    您不需要取消引用结果以导致未定义的行为 - 添加本身的效果未定义。

    也就是说

    int p[1] = {0};
    int *q = p;  // OK
    q = q + 1;   // OK - one past the end
    int *r = q + 1;   // Undefined behaviour
    r = r - 1;   // Doesn't make r valid or the program un-undefined
    

    同样

    int *p = nullptr;
    p++; // Undefined
    p--; // Still undefined
    

答案 1 :(得分:3)

&#34;评估&#34;是指添加剂操作的评估;因此,在非评估的上下文(static_cast<int*>(nullptr) + 1sizeof等)中(例如)decltype不会出现UB。

它并不意味着&#34;指针的评估&#34;,当然不会解除引用它;如果标准有意这样的解释,它就会这么说。

答案 2 :(得分:0)

递增然后递减空指针仍然是未定义的行为。当UB发生时,任何事情都可能发生,因此这将是一个有效的事件序列:

  1. 增加空指针。未定义的行为,因此我们将指针设置为0xDEADBEEF,因为我们可以。
  2. 减少指针。除非0xDEADBEEF碰巧位于第一个元素之后的有效数组中,否则还会出现未定义的行为。
  3. 取消引用指针。发出鼻子恶魔。