将增量/减量运算符放在三元/条件运算符中是否安全?

joz*_*yqk 26 c c++ increment ternary-operator decrement

这是一个例子

#include <iostream>
using namespace std;
int main()
{   
    int x = 0;
    cout << (x == 0 ? x++ : x) << endl; //operator in branch
    cout << "x=" << x << endl;
    cout << (x == 1 || --x == 0 ? 1 : 2) << endl; //operator in condition
    cout << "x=" << x << endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:

0
x=1
1
x=1
Run Code Online (Sandbox Code Playgroud)

我理解输出,但这是不确定的行为?在任何一种情况下,评估顺序是否得到保证?

即使有保证,我也非常清楚使用递增/递减会很快成为可读性的问题.我只是问我看到类似的代码并且立即不确定,因为有很多关于递增/递减运算符的模糊/未定义使用的示例,例如......

T.C*_*.C. 34

对于条件运算符(§5.16[expr.cond]/p1):

在与第二或第三表达式相关联的每个值计算和副作用之前,对与第一表达式相关联的每个值计算和副作用进行排序.

对于逻辑OR运算符(§5.15[expr.log.or]/p1-2):

如果第一个操作数的计算结果为,则不计算第二个操作数true.[...]如果计算第二个表达式,则在每个值计算和与第二个表达式相关的副作用之前,对与第一个表达式相关联的每个值计算和副作用进行排序.

代码的行为是明确定义的.


Cas*_*Cow 10

有三元运营商和布尔执行的保证的顺序&&||操作,因此在评估序列点没有冲突.

一次一个

 cout << (x == 0 ? x++ : x) << endl; //operator in branch
Run Code Online (Sandbox Code Playgroud)

将始终输出,x但只有在它为0时才会增加.

 cout << (x == 1 || --x == 0 ? 1 : 2) << endl; //operator in condition
Run Code Online (Sandbox Code Playgroud)

这个定义也很明确,如果x是1则不会评估RHS,如果不是它会减少它但是--x永远不会是0,所以如果x == 1那么它将是真的,在这种情况下x现在也将是0 .

在后一种情况下,如果x是INT_MIN没有明确定义的行为来减少它(并且它将执行).

在第一种情况下不会发生这种情况,如果它是INT_MAX安全的,则x不会为0 .


hac*_*cks 8

我理解输出,但这是不确定的行为?

代码完美定义.C11标准说:

6.5.15条件运算符

第一个操作数被评估; 在其评估与第二或第三操作数的评估之间存在一个序列点(以评估者为准).仅当第一个操作数与第一个操作数不相等时,才评估第二个操作数0; 仅当第一个操作数比较等于时,才评估第三个操作数0; 结果是第二个或第三个操作数的值(无论哪个被评估),转换为下面描述的类型.110)

6.5.14逻辑OR运算符

不同的是按位|运营商,||运营商保证左到右的评价 ; 如果计算第二个操作数,则在第一个和第二个操作数的计算之间存在一个序列点.如果第一个操作数与不相等0,则不计算第二个操作数.

进一步维基用例子解释:

  • 在评估&&(逻辑AND)的左右操作数之间,||(逻辑OR)(作为短路评估的一部分),和comma operators.例如,在表达式中*p++ != 0 && *q++ != 0,子表达式的所有副作用*p++ != 0都在任何访问尝试之前完成q.

  • 在评估三元"问号"运算符的第一个操作数和第二个或第三个操作数之间.例如,在表达式中,在第a = (*p++) ? (*p++) : 0一个之后存在一个序列点*p++,这意味着它已经在第二个实例执行时增加了.

对于C++(第5.15和5.16节)的规则||?:C相同,与C相同.


在任何一种情况下,评估顺序是否得到保证?

是.运营商的操作数的计算顺序||,&&,,?:保证从左至右.

  • 在||处有一个序列点 还有,所以#2也行.> (4认同)
  • @Slava; 你是毫无意义的争论.再次阅读我的回答. (3认同)
  • @Slava; 哦! 它是如何误导的?你能解释一下吗? (2认同)
  • @Slava; 哪一个有UB? (2认同)