什么是"序列点"?
未定义的行为和序列点之间的关系是什么?
我经常使用有趣和复杂的表达方式a[++i] = i;,让自己感觉更好.我为什么要停止使用它们?
如果您已阅读此内容,请务必访问后续问题重新加载未定义的行为和序列点.
(注意:这是Stack Overflow的C++常见问题解答的一个条目.如果你想批评在这种形式下提供常见问题解答的想法,那么发布所有这些的元数据的发布将是这样做的地方.这个问题在C++聊天室中受到监控,其中FAQ的想法一开始就出现了,所以你的答案很可能被那些提出想法的人阅读.)
我已经看到了其他类似的问题,并阅读了有关它的缺陷.但我仍然没有得到它.为什么i = ++i + 1在C++ 11中定义得很好i = i++ + 1?该标准如何明确定义?
通过我的工作,我在图之前有以下顺序(其中箭头表示关系之前的顺序,除非另有说明,否则一切都是值计算):
i = ++i + 1
^
|
assignment (side effect on i)
^ ^
| |
?i ++i + 1
|| ^
i+=1 |
^ 1
|
?assignment (side effect on i)
^ ^
| |
i 1
Run Code Online (Sandbox Code Playgroud)
我i用黑星标记了一个副作用,i用白星计算了一个值.这些似乎相互之间没有相应的顺序(根据我的逻辑).标准说:
如果对标量对象的副作用相对于同一标量对象的另一个副作用或使用相同标量对象的值进行的值计算未被排序,则行为未定义.
缺陷报告中的解释并没有帮助我理解.左值到右值的转换与任何事情有什么关系?我弄错了什么?
在C++ 11标准的上下文中(不再有序列点的概念,如您所知),我想了解如何定义两个最简单的示例.
int i = 0;
i = i++; // #0
i = ++i; // #1
Run Code Online (Sandbox Code Playgroud)
SO上有两个主题可以解释C++ 11环境中的这些示例.这里据说#0调用UB并且#1定义明确.这里有人说,这两个例子是不确定的.这种模棱两可让我很困惑.我已经三次读过这个结构良好的参考文献,但这个主题似乎对我来说太复杂了.
.
让我们分析一下这个例子#0:i = i++;.
相应的报价是:
内置后增量和后减量运算符的值计算在其副作用之前进行排序.
内置赋值运算符和所有内置复合赋值运算符的副作用(左参数的修改)在左右参数的值计算(但不是副作用)之后排序,并在之前排序赋值表达式的值计算(即,在返回对修改对象的引用之前)
如果相对于同一标量对象的另一个副作用,标量对象的副作用未被排序,则行为未定义.
当我得到它时,赋值运算符的副作用没有按其左右参数的副作用排序.因此,赋值运算符的副作用没有按副作用排序i++.所以#0调用一个UB.
.
让我们分析一下这个例子#1:i = ++i;.
相应的报价是:
内置preincrement和predecrement运算符的副作用在其值计算之前被排序(由于定义为复合赋值的隐式规则)
内置赋值运算符和所有内置复合赋值运算符的副作用(左参数的修改)在左右参数的值计算(但不是副作用)之后排序,并在之前排序赋值表达式的值计算(即,在返回对修改对象的引用之前)
如果相对于同一标量对象的另一个副作用,标量对象的副作用未被排序,则行为未定义.
我看不出,这个例子是怎样的#0.对于我而言,这似乎是一个UB,原因与此相同#0.分配的副作用没有按照副作用排序++i.它似乎是一个UB.上面讨论的主题说它定义明确.为什么?
.
问题:如何应用引用规则来确定示例的UB.一个尽可能简单的解释将不胜感激.谢谢!
我在项目中使用Coverity Prevent来查找错误.
它报告此表达式的错误(变量名称当然已更改):
x=
(a>= b) ?
++x: 0;
Run Code Online (Sandbox Code Playgroud)
消息是:
EVALUATION_ORDER缺陷:在"
x=(a>= b) ? ++x: 0;"中,"x"写在"x"(赋值LHS)中并用"(a>= b) ? ++x: 0;" 写入,但副作用发生的顺序是不确定的,因为没有中间序列点.消息结束
虽然我可以理解" x = x++"是不确定的,但这对我来说有点困难.这个是假阳性吗?