为什么带逗号的三元运算符在真实情况下只计算一个表达式? [英] Why does the ternary operator with commas evaluate only one expression in the true case?
问题描述
我目前正在通过《C++ Primer》这本书学习 C++,书中的一个练习是:
I'm currently learning C++ with the book C++ Primer and one of the exercises in the book is:
解释以下表达式的作用: someValue ?++x, ++y : --x, --y
Explain what the following expression does:
someValue ? ++x, ++y : --x, --y
我们知道什么?我们知道三元运算符的优先级高于逗号运算符.对于二元运算符,这很容易理解,但是对于三元运算符,我有点挣扎.对于二元运算符,具有更高优先级"意味着我们可以在具有更高优先级的表达式周围使用括号,并且不会改变执行.
What do we know? We know that the ternary operator has a higher precedence than the comma operator. With binary operators this was quite easy to understand, but with the ternary operator I am struggling a bit. With binary operators "having higher precedence" means that we can use parentheses around the expression with higher precedence and it will not change the execution.
对于三元运算符,我会这样做:
For the ternary operator I would do:
(someValue ? ++x, ++y : --x, --y)
有效地产生相同的代码,这无助于我理解编译器如何对代码进行分组.
effectively resulting in the same code which does not help me in understanding how the compiler will group the code.
但是,通过使用 C++ 编译器进行测试,我知道表达式可以编译,但我不知道 :
运算符本身可以代表什么.所以编译器似乎正确地解释了三元运算符.
However, from testing with a C++ compiler I know that the expression compiles and I do not know what a :
operator could stand for by itself. So the compiler seems to interpret the ternary operator correctly.
然后我以两种方式执行程序:
Then I executed the program in two ways:
#include <iostream>
int main()
{
bool someValue = true;
int x = 10, y = 10;
someValue ? ++x, ++y : --x, --y;
std::cout << x << " " << y << std::endl;
return 0;
}
结果:
11 10
另一方面,使用 someValue = false
它打印:
While on the other hand with someValue = false
it prints:
9 9
为什么 C++ 编译器生成的代码对于三元运算符的真分支只增加 x
,而对于三元运算符的假分支它同时减少 x
和 y
?
Why would the C++ compiler generate code that for the true-branch of the ternary operator only increments x
, while for the false-branch of the ternary it decrements both x
and y
?
我什至像这样在真正的分支周围加上括号:
I even went as far as putting parentheses around the true-branch like this:
someValue ? (++x, ++y) : --x, --y;
但结果仍然是 11 10
.
推荐答案
正如 @Rakete 在他们出色的回答中所说,这很棘手.我想补充一点.
As @Rakete said in their excellent answer, this is tricky. I'd like to add on to that a little.
三元运算符必须具有以下形式:
The ternary operator must have the form:
逻辑或表达式 ?
表达式 :
赋值表达式
所以我们有以下映射:
someValue
: 逻辑或表达式++x, ++y
: 表达式- ???是 assignment-expression
--x, --y
还是只有--x
?
someValue
: logical-or-expression++x, ++y
: expression- ??? is assignment-expression
--x, --y
or only--x
?
实际上只是--x
,因为一个赋值表达式不能解析为两个用逗号隔开的表达式(按照C++的语法规则),所以--x, --y
不能被视为赋值表达式.
In fact it is only --x
because an assignment expression cannot be parsed as two expressions separated by a comma (according to C++'s grammar rules), so --x, --y
cannot be treated as an assignment expression.
这导致三元(条件)表达式部分如下所示:
Which results in the ternary (conditional) expression portion to look like this:
someValue?++x,++y:--x
为了可读性,考虑将 ++x,++y
计算为 as-if 括号 (++x,++y)
;?
和 :
之间包含的任何内容都将在条件之后排序.(我将在文章的其余部分用括号括起来).
It may help for readability's sake to consider ++x,++y
to be computed as-if parenthesized (++x,++y)
; anything contained between ?
and :
will be sequenced after the conditional. (I'll parenthesize them for the rest of the post).
并按以下顺序评估:
someValue?
(++x,++y)
或--x
(取决于bool
1 的结果.)
someValue?
(++x,++y)
or--x
(depending onbool
result of 1.)
这个表达式然后被视为逗号运算符的左子表达式,右子表达式是--y
,如下所示:
This expression is then treated as the left sub-expression to a comma operator, with the right sub-expression being --y
, like so:
(someValue?(++x,++y):--x), --y;
这意味着左侧是一个丢弃值表达式,这意味着它肯定会被评估,但是我们评估右侧并返回它.
Which means the left side is a discarded-value expression, meaning that it is definitely evaluated, but then we evaluate the right side and return that.
那么当 someValue
为 true
时会发生什么?
So what happens when someValue
is true
?
(someValue?(++x,++y):--x)
执行并增加x
和y
为11
和11
- 左边的表达式被丢弃(尽管增量的副作用仍然存在)
- 我们评估逗号运算符的右侧:
--y
,然后将y
递减回10
(someValue?(++x,++y):--x)
executes and incrementsx
andy
to be11
and11
- The left expression is discarded (though the side effects of increment remain)
- We evaluate the right hand side of the comma operator:
--y
, which then decrementsy
back to10
要修复"该行为,您可以将 --x, --y
与括号组合在一起,将其转换为 是 的主要表达式strong> 赋值表达式* 的有效条目:
To "fix" the behavior, you can group --x, --y
with parentheses to transform it into a primary expression which is a valid entry for an assignment-expression*:
someValue?++x,++y:(--x, --y);
<小时>
*这是一个相当有趣的长链,将赋值表达式连接回主表达式:
赋值表达式 ---(可以包含)--> 条件表达式 --> 逻辑或表达式 --> 逻辑与表达式 --> inclusive-or-expression --> exclusive-or-expression --> and-expression --> equality-expression --> 关系表达式 --> shift-expression --> 加法表达式 --> 乘法表达式 --> pm-expression --> cast-expression --> 一元表达式 --> 后缀表达式 --> 主表达式
assignment-expression ---(can consist of)--> conditional-expression --> logical-or-expression --> logical-and-expression --> inclusive-or-expression --> exclusive-or-expression --> and-expression --> equality-expression --> relational-expression --> shift-expression --> additive-expression --> multiplicative-expression --> pm-expression --> cast-expression --> unary-expression --> postfix-expression --> primary-expression
这篇关于为什么带逗号的三元运算符在真实情况下只计算一个表达式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!