评估顺序和不确定的行为

科柳尼亚

在C ++ 11标准(您不再知道序列点的概念)的背景下,我想了解如何定义两个最简单的示例。

int i = 0;

i = i++;   // #0

i = ++i;   // #1

SO有两个主题,它们解释了C ++ 11上下文中的这些示例。这里有人说,#0所调用UB和#1被明确定义的。这里有人说,这两个例子是不确定的。这种含糊不清使我非常困惑。我已经阅读了三本结构良好的参考书,但是对于我来说,这个话题似乎太复杂了。

让我们分析示例#0i = i++;

相应的引号是:

  • 内置后递增和后递减运算符的值计算在其副作用之前进行排序。

  • 内置赋值运算符和所有内置复合赋值运算符的副作用(对左参数的修改)在左,右参数的值计算(但不是副作用)之后进行排序,并在排序之前赋值表达式的值计算(即,在将引用返回修改后的对象之前)

  • 如果相对于同一标量对象上的另一个副作用,未对标量对象上的副作用进行排序,则该行为未定义。

据我所知,赋值运算符的副作用并未与其左,右参数的副作用排序。因此,赋值运算符的副作用未与的副作用排序i++因此#0调用UB。

让我们分析示例#1i = ++i;

相应的引号是:

  • 内置的预增和预减运算符的副作用在其值计算之前进行排序(由于定义为复合赋值,因此存在隐式规则)

  • 内置赋值运算符和所有内置复合赋值运算符的副作用(对左参数的修改)在左,右参数的值计算(但不是副作用)之后进行排序,并在排序之前赋值表达式的值计算(即,在将引用返回修改后的对象之前)

  • 如果相对于同一标量对象上的另一个副作用,未对标量对象上的副作用进行排序,则该行为未定义。

我看不到,这个例子与的不同之处#0对我来说,这似乎是UB,原因与相同#0赋值的副作用未与的副作用排序++i好像是UB。上面喜欢的主题说,它定义明确。为什么?

问题:如何应用引用规则来确定示例的UB。尽可能简单的解释将不胜感激。谢谢!

兆瓦

由于您的报价并非直接来自标准,因此我将尝试提供详细的答案,并引用标准的相关部分。在第1.9 / 12段中可以找到“副作用”和“评估”的定义:

访问由易失性glvalue(3.10)指定的对象,修改对象,调用库I / O函数或调用执行任何这些操作的函数都是副作用,它们都是执行环境状态的变化。表达式(或子表达式)的评估通常包括值计算(包括确定对象的身份以进行glvalue评估和获取先前分配给对象的值以进行prvalue评估)和副作用的初始化。

下一个相关部分是第1.9 / 15段:

除非另有说明,否则对单个运算符的操作数和单个表达式的子表达式的求值是无序列的。…………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………… 如果相对于同一标量对象上的另一副作用或使用同一标量对象的值进行的值计算,未对标量对象的副作用进行排序,则该行为未定义。

现在让我们看看如何将其应用于两个示例。

i = i++;

这是增量的后缀形式,您可以在第5.2.6段中找到其定义。最相关的句子是:

++表达式的值计算在修改操作数对象之前进行排序。

有关赋值表达式,请参见第5.17段。相关部分指出:

在所有情况下,赋值的顺序在左右操作数的值计算之后,在赋值表达式的值计算之前。

使用上面的所有信息,整个表达式的计算结果是(标准不保证该顺序!):

  • i++(右侧)的值计算
  • i(左手边)的值计算
  • i(的副作用++)的修改
  • i(的副作用=)的修改

所有标准保证是两个操作数的值计算在赋值表达式的值计算之前进行排序。但是,右侧的值计算只是“读取”的值,i不是修改i,两个修改(副作用)没有相对于彼此排序,因此我们得到不确定的行为。

那第二个例子呢?

i = ++i;

这里的情况截然不同。您可以在第5.3.2节中找到前缀增量的定义。相关部分是:

如果x不是bool类型,则表达式++ x等效于x + = 1。

代之以,我们的表达式等于

i = (i += 1)

+=在5.17 / 7中查找复合赋值运算符,我们得到的结果i += 1与等效,i = i + 1除了i只评估一次。因此,所讨论的表达式最终变为

i =(i =(i + 1))

但是我们已经从上面知道,的值计算=在操作数的值计算之后进行,而副作用在的值计算之前进行排序=因此,我们得到了明确定义的评估顺序:

  1. 计算i + 1(和i-内部表达式的左手边)的值(#1)
  2. 引发inner的副作用=,即修改“ inner”i
  3. 计算的值(i = i + 1),即的“新”值i
  4. 引发外部的副作用=,即修改“外部”i
  5. 计算完整表达式的值。

(#1):在这里,i只计算一次,因为i += 1等效于i = i + 1不同的是i仅一次(5.17 / 7)进行评价。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

排序时更改排序顺序是不确定的行为吗?

来自分类Dev

不确定的行为?

来自分类Dev

“不确定的行为”总是不确定的吗?

来自分类Dev

“不确定的行为”总是不确定的吗?

来自分类Dev

短路评估不确定吗?

来自分类Dev

增量运算符和“不确定行为”

来自分类Dev

在评估潜在常数表达式期间的不确定行为

来自分类Dev

在评估潜在常数表达式期间的不确定行为

来自分类Dev

销毁期间行为不确定?

来自分类Dev

关于对象的不确定行为

来自分类Dev

Python 3的不确定行为

来自分类Dev

这是不确定的行为吗?

来自分类Dev

这是不确定的行为还是误报?

来自分类Dev

HHVM类型检查器的不确定行为

来自分类Dev

不确定的行为导致时间旅行

来自分类Dev

遗漏是某种不确定的行为吗?

来自分类Dev

测试python函数的不确定行为

来自分类Dev

Python multiprocessing.Process行为不确定

来自分类Dev

避免不确定的行为:临时对象

来自分类Dev

何时移位会导致不确定的行为

来自分类Dev

Python 2.7 Ctrl + C不确定行为

来自分类Dev

LLVM / LLDB的不确定行为(XCode 5.1.1)

来自分类Dev

python relativedelta中的不确定行为

来自分类Dev

bash脚本中不确定的行为,用于打开和命名屏幕窗口

来自分类Dev

这是C语言的不确定行为吗?在clang和GCC中的结果不同

来自分类Dev

带有`throw`和字符串连接的不确定行为

来自分类Dev

奇怪的维度行为:需要维度 2 和维度 3 不确定为什么

来自分类Dev

为什么在printStackTrace()和其他方法之间的执行顺序似乎不确定?

来自分类Dev

对于使用应用顺序评估和基于正常顺序的解释器的解释器,我会看到什么行为?

Related 相关文章

热门标签

归档