【问题标题】:Is *p++ += 2 well defined?*p++ += 2 定义明确吗?
【发布时间】:2014-12-12 13:42:00
【问题描述】:

我不确定下面的语句是否被标准 C 很好地定义了

*p1++ += 2;

或其他类似声明:

*E1++ <operator>= E2

来自标准 C 关于后增量:

后缀 ++ 运算符的结果是操作数的值。 得到结果后,操作数的值递增。 (即,将相应类型的值 1 添加到它。)请参阅 加法运算符和复合赋值的讨论 有关约束、类型和转换以及影响的信息 对指针的操作。更新存储值的副作用 操作数的发生在前一个序列和下一个序列之间 点。

关于复数赋值:

E1 op= E2 形式的复合赋值不同于简单的赋值 赋值表达式 E1 = E1 op (E2) 只是因为左值 E1 是 只评估一次。

【问题讨论】:

  • 好吧,究竟是什么引发了您对它可能未定义的怀疑?例如,对我来说,一切看起来都很好,这让我什至很难开始回答这个问题:我不知道该关注什么。
  • 不要在这样的项目中写代码,除非你研究它。
  • 编写这种难以辨认的代码只是为了在一行中塞入更多代码是糟糕的编程。 :)
  • 谁在乎。如果此代码是任何真实程序,它将立即被删除。实际上,它永远不应该通过代码审查并进入代码库。因此,它是否符合原始开发人员的期望是无关紧要的,因为下一个开发人员将​​不会立即理解它,从而将其从代码库中重构出来。
  • 这个问题是相关的,如果有更广泛的背景,例如“我的程序在使用 GCC 和 Visual C++ 编译时表现不同。我在其中遇到了这一行 - 这可能是问题吗?”

标签: c++ c pointers post-increment compound-assignment


【解决方案1】:

后缀增量运算符 (++) 给出操作数的值,即它给出一个 r-value。 r 值意味着它在赋值运算符 (=) 的左侧用作操作数。

int i = 0;
i++ = 0   // [Error] lvalue required as left operand of assignment  

如果发生

*p1++ += 2;  

后缀++ 不应用于*p1,但应用于指针p1++。这是因为后缀++ 的优先级高于取消引用运算符*。因此,编译器会将上述语句解析为

*(p1++) += 2;

这就是说:

  • 在添加 2 并将结果分配给它之前,必须评估 *p1(以生成变量)。
  • 存储到*p1 的结果必须在递增到p1 之前进行评估。
  • 一旦评估了*p1p1 就可以随时递增。

【讨论】:

  • C++ 中是否保证最后一条语句?
  • 我原以为一旦 p1 被评估,p1 可以随时递增。
【解决方案2】:

让我们稍微重写一下以使其更清晰:

(*p1++) += 2

所以p1 的旧值将被取消引用,并且 2 将添加到其所指对象。并且p1 将在它被取消引用后递增(或者至少在它的旧值被加载并等待被取消引用之后)。这里没有问题:没有一个部件被使用超过一次。

话虽如此,为了清晰起见,您应该考虑重写代码:

*p1 += 2;
++p1;

【讨论】:

  • "then" 不太正确,+= 的副作用可能发生在 ++ 的副作用之前或之后。它们的关键是它们位于不同的标量对象上。
猜你喜欢
  • 1970-01-01
  • 2018-08-28
  • 1970-01-01
  • 2022-01-24
  • 2011-06-10
  • 1970-01-01
  • 2011-08-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多