Auf*_*gel 118 c++ conditional-operator operator-precedence language-lawyer
我目前正在学习使用C++ Primer一书的C++,本书的其中一个练习是:
解释以下表达式的作用:
someValue ? ++x, ++y : --x, --y
我们知道什么?我们知道三元运算符的优先级高于逗号运算符.使用二元运算符这很容易理解,但是对于三元运算符,我有点挣扎.使用二元运算符"具有更高的优先级"意味着我们可以使用具有更高优先级的表达式周围的括号,并且它不会更改执行.
对于三元运算符,我会这样做:
(someValue ? ++x, ++y : --x, --y)
Run Code Online (Sandbox Code Playgroud)
有效地产生相同的代码,这无法帮助我理解编译器如何对代码进行分组.
但是,通过使用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;
}
Run Code Online (Sandbox Code Playgroud)
结果是:
11 10
Run Code Online (Sandbox Code Playgroud)
而另一方面someValue = false
它与它打印:
9 9
Run Code Online (Sandbox Code Playgroud)
为什么C++编译器生成的代码只能为三元运算符的真分支递增x
,而对于三元的假分支,它会减少x
和y
?
我甚至把括号括在真正的分支周围,就像这样:
someValue ? (++x, ++y) : --x, --y;
Run Code Online (Sandbox Code Playgroud)
但它仍然会导致11 10
.
And*_*dyG 121
正如@Rakete在他们出色的回答中所说,这很棘手.我想补充一点.
三元运算符必须具有以下形式:
逻辑或表达式
?
表达式:
赋值表达式
所以我们有以下映射:
someValue
:logical-or-expression++x, ++y
:表达--x, --y
还是仅--x
?实际上,这只是--x
因为赋值表达式不能被解析为用逗号分隔的两个表达式(根据C++的语法规则),因此--x, --y
不能将其视为赋值表达式.
这导致三元(条件)表达式部分看起来像这样:
someValue?++x,++y:--x
Run Code Online (Sandbox Code Playgroud)
它可以帮助提高可读性的缘故考虑++x,++y
到计算的,如果括号(++x,++y)
; 包含之间的任何东西?
和:
将被测序后的条件.(我会在帖子的其余部分将它们括起来).
并按此顺序评估:
someValue?
(++x,++y)
或--x
(取决于bool
1的结果)然后将此表达式视为逗号运算符的左子表达式,右子表达式--y
如下:
(someValue?(++x,++y):--x), --y;
Run Code Online (Sandbox Code Playgroud)
这意味着左侧是一个丢弃值表达式,意味着它被明确地评估,但是然后我们评估右侧并返回它.
当会发生什么someValue
是true
?
(someValue?(++x,++y):--x)
执行和增加x
并y
成为11
和11
--y
然后递减y
回来10
要"修复"该行为,可以--x, --y
使用括号进行分组,将其转换为主表达式,该表达式是赋值表达式*的有效条目:
someValue?++x,++y:(--x, --y);
Run Code Online (Sandbox Code Playgroud)
*这是一个相当有趣的长链,它将赋值表达式连接回主表达式:
assignment-expression ---(可以包含) - > 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
Rak*_*111 87
哇,这太棘手了.
编译器将您的表达式视为:
(someValue ? (++x, ++y) : --x), --y;
Run Code Online (Sandbox Code Playgroud)
三元运算符需要a :
,它在该上下文中不能独立,但在它之后,没有理由为什么逗号应该属于false case.
现在,为什么你得到那个输出可能更有意义.如果someValue
是,那么++x
,++y
并--y
执行,这不会有效地改变,y
但添加一个x
.
如果someValue
是假的,那么--x
和--y
执行,由一个递减他们.
das*_*ght 42
为什么C++编译器会生成三元运算符的真分支仅递增的代码
x
你误解了发生了什么.真正的分支增加x
和y
.但是,y
在此之后立即无条件地减少.
以下是这种情况:由于条件运算符的优先级高于C++中的逗号运算符,编译器将按如下方式解析表达式:
(someValue ? ++x, ++y : --x), (--y);
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^
Run Code Online (Sandbox Code Playgroud)
注意--y
逗号后面的"孤立" .这是导致y
最初递增的递减的原因.
我甚至把括号括在真正的分支周围,就像这样:
Run Code Online (Sandbox Code Playgroud)someValue ? (++x, ++y) : --x, --y;
你是在正确的道路上,但你把一个错误的分支括起来:你可以通过括号化else分支来解决这个问题,如下所示:
someValue ? ++x, ++y : (--x, --y);
Run Code Online (Sandbox Code Playgroud)
你的问题是三元表达式的优先级并不高于逗号.实际上,C++不能简单地通过优先级来准确描述 - 它正是三元运算符和逗号分解之间的交互.
a ? b++, c++ : d++
Run Code Online (Sandbox Code Playgroud)
被视为:
a ? (b++, c++) : d++
Run Code Online (Sandbox Code Playgroud)
(逗号的行为就像它具有更高的优先级).另一方面,
a ? b++ : c++, d++
Run Code Online (Sandbox Code Playgroud)
被视为:
(a ? b++ : c++), d++
Run Code Online (Sandbox Code Playgroud)
并且三元运算符具有更高的优先级.
归档时间: |
|
查看次数: |
6954 次 |
最近记录: |