如何在 C++ 中处理关系运算符的优先级

How Precedence of Relational Operator handled in C++

根据 precedence rules <, >, <=, >= 优先于 !=, == 我很困惑下面的语句将如何执行

int a=3, b=3;
cout<< (a != b || a <= b);

我知道短路评估,根据优先规则,我猜编译器将首先执行 a <= b,因为它优先于 !=,但它没有这样做。

我通过更改 a <= b-- 和更改上述条件的顺序对上述语句进行了一些实验,似乎 <=!= 与编译器执行的优先级相同,以先发生者为准。或者我遗漏了什么?

发件人:https://en.cppreference.com/w/cpp/language/operator_logical

您正在寻找 ( ) 中的部分

内置运算符 && 和 ||执行短路评估(如果在评估第一个操作数后结果已知,则不评估第二个操作数),但重载运算符的行为类似于常规函数调用,并且始终评估两个操作数

所以 a != b 将首先计算。

在你的情况下 3 != 3 因此将计算第二个操作数。

if( (5<5) || (5!=5) || (5==5) || (5>5) )

优先级从左到右,所以 5<5,转到下一个 5!=5 转到下一个 5==5 操作数,如果 returns 为真且 5>5 未计算。

优先级不是评估顺序。

优先级是关于放置括号的位置。 a != b || a <= b 被解析为:(a != b) || (a <= b)。它不会被解析为例如:a != (b || (a <= b))( ).

的任何其他组合

知道括号在哪里后,我们就可以计算表达式了。评价顺序为:(a != b)在前。然后 || 被评估。然后,可选地,评估 a <= b

运算符的优先级只与表达式的绑定方式有关,与它们的执行方式无关。执行顺序取决于“先于发生”关系,否则会受到编译器任意重新排序的影响。

两个运算符的相对优先级也仅在它们直接相邻时才重要。在 a == b <= c 中,您得到 a == (b <= c),而不是 (a == b) <= c。在a == b || c <= d中,相邻的对是==||||<=。在这两种情况下,比较运算符的绑定都更强,所以你得到 (a == b) || (c <= d),使得 ==<= 的相对优先级无关紧要。如果你有 a == b + c <= d,你首先得到 a == (b + c) <= d,现在你需要再次比较 ==<=,得到你 a == ((b + c) <= d).

至于评估顺序,|| 有一个规则,它的左侧先于右侧排序(假设它没有超载),因为右侧可能根本不会被评估。所以 == 首先执行。但是优先级在这方面根本没有作用。如果你改为编写非短路 a != b | a <= b,双方最终都会被执行(注意事项,见下文),但不能保证哪一方首先被评估;优先级在这里不起作用。

警告:编译器仍然可以优化您的代码并意识到 a != b || a <= b 是同义反复,并简单地将整个代码替换为 true

根据Microsoft doc,

运算符 <= >= < > 的优先级高于运算符 != ==。但是当您应用逻辑或 || 运算符时,表达式将从左到右执行。

会按( ( a != b ) || ( a <= b ) )的意思来处理,首先( a != b )会被校验,然后是逻辑||,如果有需要的话( a <= b )会被检查(仅当第一个表达式 ( a != b ) 错误时)。