我目前正在使用C ++ Primer一书学习C ++,本书的其中一个练习是:
解释以下表达式的作用:
someValue ? ++x, ++y : --x, --y
我们知道什么?我们知道三元运算符的优先级高于逗号运算符。使用二元运算符这很容易理解,但是对于三元运算符,我有点挣扎。使用二元运算符"具有更高的优先级"意味着我们可以在具有更高优先级的表达式周围使用括号,并且不会更改执行。
对于三元运算符,我会这样做:
(someValue ? ++x, ++y : --x, --y)
有效地产生了相同的代码,这些代码无法帮助我理解编译器如何对代码进行分组。
然而,通过使用C ++编译器进行测试,我知道表达式编译,我不知道:
运算符本身可以代表什么。所以编译器似乎正确地解释了三元运算符。
然后我以两种方式执行该程序:
#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
打印出来:
9 9
为什么C ++编译器生成的代码对于三元运算符的真分支仅增加x
,而对于三元的假分支,它会减少x
和{{1} }?
我甚至将括号括在真正的分支上,如下所示:
y
但仍然会产生someValue ? (++x, ++y) : --x, --y;
。
答案 0 :(得分:121)
正如@Rakete在他们出色的回答中所说,这很棘手。我想稍微补充一下。
三元运算符必须具有以下形式:
logical-or-expression
?
表达式:
assignment-expression
所以我们有以下映射:
someValue
: logical-or-expression ++x, ++y
:表达 --x, --y
或仅--x
?实际上它只是--x
因为赋值表达式不能被解析为用逗号分隔的两个表达式(根据C ++的语法规则),所以--x, --y
不能视为赋值表达式。
这导致三元(条件)表达式部分看起来像这样:
someValue?++x,++y:--x
为了便于阅读,可以考虑将++x,++y
计算为,如果括号(++x,++y)
; 1}}和?
之间包含的任何内容都将在条件之后排序。 (我会在帖子的其余部分用括号括起来。)
并按此顺序进行评估:
:
someValue?
或(++x,++y)
(取决于--x
1的结果。)然后将此表达式视为逗号运算符的左子表达式,右侧子表达式为bool
,如下所示:
--y
这意味着左侧是废弃值表达式,这意味着它是明确评估的,但随后我们评估右侧并返回它。
那么当(someValue?(++x,++y):--x), --y;
为someValue
时会发生什么?
true
执行并将(someValue?(++x,++y):--x)
和x
增加为y
和11
11
,然后将--y
递减回y
To&#34; fix&#34;在行为方面,您可以将10
与括号分组,将其转换为主表达式,其中 是赋值表达式的有效条目 *:
--x, --y
*这是一个相当有趣的长链,它将赋值表达式连接回主表达式:
赋值表达式 ---(可以包含) - &gt; 条件表达式 - &gt; logical-or-expression - &gt; 逻辑与表达 - &gt; 包含或表达 - &gt; exclusive-or-expression - &gt; and-expression - &gt; equality-expression - &gt; relational-expression - &gt; shift-expression - &gt; additive-expression - &gt; 乘法表达式 - &gt; pm-expression - &gt; cast-expression - &gt; 一元表达 - &gt; postfix-expression - &gt; 基本表达式
答案 1 :(得分:87)
编译器将您的表达式视为:
(someValue ? (++x, ++y) : --x), --y;
三元运算符需要:
,它不能在该上下文中独立存在,但在此之后,没有理由为什么逗号应属于错误情况。
现在,为什么你得到那个输出可能更有意义。如果someValue
为真,那么++x
,++y
和--y
会被执行,这不会有效地更改y
,但会向x
添加一个someValue
如果--x
为false,则执行--y
和web.xml
,将它们减1。
答案 2 :(得分:42)
为什么C ++编译器会生成三元运算符的真分支只增加
的代码x
你误解了发生的事情。真分支增加x
和y
。但是,y
在此之后立即无条件地递减。
以下是这种情况:自the conditional operator has higher precedence than comma operator in C++以来,编译器按如下方式解析表达式:
(someValue ? ++x, ++y : --x), (--y);
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^
注意&#34;孤儿&#34;逗号后--y
。这导致最初增加的y
递减。
我甚至将括号括在真正的分支上,如下所示:
someValue ? (++x, ++y) : --x, --y;
你是在正确的道路上,但你把一个错误的分支括起来:你可以通过括号化else分支来解决这个问题,如下所示:
someValue ? ++x, ++y : (--x, --y);
答案 3 :(得分:5)
你的问题是三元表达式的优先级并不高于逗号。实际上,C ++不能简单地通过优先级来准确描述 - 它正是三元运算符和逗号分解之间的交互。
a ? b++, c++ : d++
被视为:
a ? (b++, c++) : d++
(逗号的行为就像它具有更高的优先级)。另一方面,
a ? b++ : c++, d++
被视为:
(a ? b++ : c++), d++
并且三元运算符具有更高的优先级。
答案 4 :(得分:2)
在答案中被忽略的一点(虽然涉及到评论)是条件运算符总是在实际代码中用于(设计意图?)作为将两个值中的一个赋值给变量的快捷方式。
所以,更大的背景是:
whatIreallyWanted = someValue ? ++x, ++y : --x, --y;
这是荒谬的,所以犯罪是多方面的: