这个三元条件表达式是如何执行的?

Posted

技术标签:

【中文标题】这个三元条件表达式是如何执行的?【英文标题】:How is this ternary conditional expression executed? 【发布时间】:2016-06-09 20:58:12 【问题描述】:
int x = 5,y = 10;
bool boolean = 0;
int k = (boolean ? ++x, ++y : --x, --y);
cout<<k;

boolean 为 0 时输出 9,但为 1 时输出 10。我知道这是由于优先级而发生的,但无法准确弄清楚它是如何发生的,请帮助我理解这一点。

注意:我知道如果我使用括号,或者更好地编写干净的代码,我可以获得预期的输出,我只是用它来了解编译器如何根据优先级评估这些表达式。

【问题讨论】:

阅读逗号运算符和前缀递增递减。 你希望得到什么输出? 请不要写这样的代码。 这就是为什么你应该编写可读代码 当您想在ifelse 的每个案例中执行多项操作时,我强烈建议您使用完整的if - else 块。此外,我发现在处理复杂表达式时添加自己的括号有助于提高可读性,即使我知道运算符优先级可以满足我的要求。 【参考方案1】:

, 的优先级低于?:。这意味着完整的括号是:

int k = ((boolean ? (++x, ++y) : --x), --y);

如您所见,k 始终初始化为 --y 的值。只是如果booleantrue++y 发生在这之前。


在查找表达式的完整括号形式时,将其视为构造表达式树(其中最低优先级的运算符位于根部)。

在表达式中找到最低优先级的运算符,并将其左侧参数和右侧参数用括号括起来。在括号内的子表达式中递归重复。

【讨论】:

谢谢,你的回答有帮助,你能告诉我在给定优先级的情况下给特定表达式加上括号的步骤吗,我无法决定为这样的表达式加上括号。 @KaranJoisher 我尝试相应地扩展答案。 @KaranJoisher 为什么不直接加上括号来消除所有歧义:int k = (boolean ? (++x, ++y) : (--x, --y)); 立即明确哪些部分去哪里。无需尝试找出运算符的优先级。 @AndreKostur 我知道如果我使用括号覆盖我可以简单地得到预期的输出,我只是想理解优先概念,如果我不使用括号编译器会做什么。 @AndreKostur 因为并非所有您试图理解的代码都是您自己编写的代码 - 自己尝试这些东西是让它牢牢记住的好方法,或者至少给出你是一个参考,当你遇到别人的“聪明”时,你可以回去参考【参考方案2】:

由于逗号运算符具有最低的operator precedence,因此您的语句实际上等于

k = (boolean ? (++x, ++y) : --x), --y;

这意味着当booleantrue 时,你既增加又减少y。三元表达式的结果在这两种情况下都被丢弃,k 只分配了--y 的结果。

应该注意,这不是未定义的行为,因为逗号运算符引入了一个序列点。


要得到你期望的结果,你需要这样做

k = boolean ? (++x, ++y) : (--x, --y);

请注意,++x, ++y 周围的括号是严格不需要的,但它确实使表达式更清晰。

【讨论】:

我想知道是否有人会谈论代码的非 UBness。谢谢你。 @NathanOliver 好吧,在这种情况下,它有点重要的。 :) @NathanOliver 你应该得到 UB 编写这样的代码。我不是编译器,我不想解析代码。 不是因为?:, 而导致的非UBness 吗?【参考方案3】:

鉴于上述出色的答案,应该改为:

if (boolean) 
     ++x;
     ++y;
 else 
     --x;
     --y;    

int k = y;

因为这样代码在其意图上更可读清晰。这将帮助任何必须维护代码的人(包括原作者!),而无需任何人浪费时间询问 SO 问题或担心 ,?: 的优先级或分配给如此复杂的后勤工作表达式是。任何现代编译器都会优化这个和上面的相同的结果代码

【讨论】:

OP 的帖子巧妙地使用了排序,但也是那种会让你的同事讨厌你的“聪明”类型。 反对的人能解释一下原因吗?我是否错过了一些非常重要的关键预优化机会,而我的代码却毫无意义?请给我一个很好的理由来编写一个初始化作为 OP。或者不要像我一样。 人们可能投反对票不是因为您的答案在技术上不正确,而是因为它并不是问题的真正答案。问题是,“这段代码是如何工作的?”你的答案是“谁在乎,写这样的代码是愚蠢的”。我 100% 同意,并认为这是一个有用的答案,所以我没有否决它。但是,在发布这些类型的答案时,您需要承担风险。你有足够的代表你不必担心它。 :-) 任何现代编译器都会将这个和上面优化成相同的结果代码 不确定,与 @ 相比,带有三元运算符的代码生成更快的汇编代码(有时相同) 987654324@-else

以上是关于这个三元条件表达式是如何执行的?的主要内容,如果未能解决你的问题,请参考以下文章

三元表达式是啥?

三元表达式

java中的条件运算符是啥?

三元运算符

java三元表达式怎么算

三元表达式,列表推导式,生成器表达式