C ++中的++ * ptr ++是未定义的行为吗?

时间:2018-12-20 18:39:16

标签: c++ language-lawyer

我在测试中被问到以下有关评估++ * ptr ++

的问题(我不想自己写。测试问了它。我仍然知道它的错误代码)

int Ar[ ] = { 6 , 3 , 8 , 10 , 4 , 6 , 7} ;
int *Ptr = Ar  ;
cout<<++*Ptr++  ;

但是,我怀疑这是未定义的行为,因为它可以是(++*ptr)++++(*ptr++)。 是吗?我不太熟悉文档,所以找不到任何东西。

2 个答案:

答案 0 :(得分:75)

  

但是我怀疑这是未定义的行为,因为它可以是(++*ptr)++++(*ptr++)。是吗?

与运行时行为(为实现者留有足够的余地)不同,在C ++中,解析本身遵循非常严格且定义明确的规则 1 。实际上,查看precedence rules时,++*Ptr++实际上被解析为++(*(Ptr++))

该技巧问题可能暗示着诸如i = ++i + ++i之类的表达式的未定义行为,其中您的值在表达式中多次出现,并由于其副作用而被修改。表达本身。这样的表达式是非法的,因为除非有一些运算符对副作用 2 进行排序,否则未定义应用它们的确切时间,因此尚不确定i的假定值是什么。在表达式的各个方面。

仍然,这里没有未定义的行为,因为表达式中的所有副作用都作用于不同的值,这些值仅在表达式中出现一次:“内部” ++影响Ptr,而外部一个会影响Ptr最初指向的值,即Ar[0]

++(*(Ptr++))
     ^^^^^____increments Ptr, returning its original value
   ^^^^^^^^______dereferences the original Ptr, AKA &Ar[0]
^^^^^^^^^^^^_______ increments Ar[0]

话虽这么说,如果我在我们的代码库中看到过这样的表达,我会竭尽全力寻找作者,并确保不会再发生这种情况。


  1. 如果有时实施起来非常奇怪和荒谬地昂贵。仍然,在标准中仍有 个未定义行为的实例描述了解析的一些极端情况,但是它比“运行时”未定义行为的普及程度低。
  2. 这些规则的简要概述can be found here;有趣的是,C ++ 17中添加了一些额外的保证。

答案 1 :(得分:23)

++*Ptr++;

不会导致U.B,并且被评估为++(*(Ptr++))

  • ptr++; /* address post incremented i.e doesn't change here itself */
  • *ptr; /* dereference same address i.e value at location where ptr earlier pointed i.e 6 */
  • ++*ptr; /* value changed where ptr pointed i.e Ar[0] becomes 7 */

请注意,帖子增量Ptr++的估算值为

  • Ptr; /* Ptr doesn't change here itself in same expression */
  • Ptr = Ptr + 1; /* in next expression, Ptr considers the incremented one */