为啥条件运算符是右结合的?

Posted

技术标签:

【中文标题】为啥条件运算符是右结合的?【英文标题】:Why is the conditional operator right associative?为什么条件运算符是右结合的? 【发布时间】:2011-11-16 11:05:00 【问题描述】:

我可以理解为什么赋值运算符是右结合的。当

x = 4 + 3

被评估,即在分配给 x 之前添加 4 和 3。

我不清楚?: 将如何从正确的联想中受益。只有当两个?:s 像这样使用时才重要吗

z = (a == b ? a : b ? c : d);

然后它是这样评估的:

z = (a == b ? a : (b ? c : d));

从左到右进行评估肯定更有意义吗?

【问题讨论】:

x = 4 + 3 中,对求值顺序的唯一限制是任何运算符的操作数必须在运算符本身被应用之前求值。 =+ 都没有对其操作数的求值施加任何排序。对于x = 4 + 3,左操作数x 和右操作数4 + 3 都必须在赋值发生之前进行求值,但这可以按任意顺序进行。请注意,评估左操作数x 是指确定要分配的对象。在更复杂的示例arr[func1()] = func2(); 中,可以按任意顺序调用这两个函数。 是的,我想我在那里不清楚/不正确。正确的联想意味着你可以做 x = y = 4;和 4 将正确分配给 y 和 x 只是为了完整性:如果分配保留关联x = y = 4 将失败。首先,y 将被分配给 x 并“返回”一个具有 y 值的右值。然后将这个右值分配给 4,这是非法的。 php 保持关联,并导致各种问题。 phpsadness.com/sad/30 【参考方案1】:

如果它从左到右评估,它看起来像这样:

z = ((a == b ? a : b) ? c : d);

也就是说,它将使用第一个条件(ab)的结果作为第二个条件的布尔条件。这没有多大意义:就像在说:

int z, tmp;
/* first conditional */
if(a == b) tmp = a;
else       tmp = b;
/* second conditional */
if(tmp) z = c;
else    z = d;

虽然也许有一天你会想要这样做,但后面的每个 ?: 更有可能是为了添加更多条件,例如 if / else if / else if / else ,这就是右关联绑定产生的结果:

int z;
/* first conditional */
if(a == b)                          z = a;
else /* second conditional */ if(b) z = c;
else                                z = d;

【讨论】:

【参考方案2】:

在任何具有右结合三元运算符的语言中,您都可以将它们堆叠起来并构建一个 if-elseif-elseif-else 表达式,如下所示:

val = a == 0 ? 1:
      a == 1 ? 2:
               4;

相反,在具有左关联三元运算符的语言中(例如 PHP,感谢@user786653),您需要用括号明确地强制执行上述意图:

<?php
// This will output 't', not 'true'.
echo (true ? 'true' : false ? 't' : 'f');

// the following is a more obvious version of the same code as above
echo ((true ? 'true' : false) ? 't' : 'f');

// here, you can see that the first expression is evaluated to 'true', which
// in turn evaluates to (bool)true, thus returning the true branch of the
// second ternary expression.
?>

【讨论】:

离题,但我忍不住链接到PHP manual 以获取 left 关联三元运算符的示例。 我会说这完全符合主题。问题是 why 条件运算符是右关联的(尽管 OP 可能不太明白这意味着什么)。 PHP 示例显示了将条件运算符定义为左关联的缺点。 我绑定编辑您的答案以修正错字,“将输出 't” 应该是“将输出 'f'”。我的编辑被保留以供同行评审。 为什么你认为有错字?运行示例。 也可以nested if;喜欢例如:a &gt; b ? a &gt; c : a : c : b &gt; c ? b : c; 就像(a &gt; b ? (a &gt; c : a : c) : (b &gt; c ? b : c));【参考方案3】:

你把关联性的概念弄错了。

当运算符+ 被称为左关联时,这意味着a + b + c 等效于(a + b) + c,而不是a + (b + c)

运算符= 是右关联的,这意味着a = b = c 等效于a = (b = c),而不是(a = b) = c

关联性与求值顺序无关。

【讨论】:

"关联性与求值顺序无关。"好吧,除非所有运算符的优先级相同。 我指的是在分配给x之前添加了4和3。运算符的右手边还是左手边先求值,与关联性无关。而且无论运算符是右结合还是左结合,操作数都必须在执行实际操作之前进行计算。 您对添加/分配的事情是正确的,澄清这一点很好,但这并不是 OP 的真正目的,他的陈述可以很容易地修改为“我理解为什么 @987654329 @ 返回 1 而不是 3。”到目前为止,你所说的一切都与他关于为什么 ?: 是正确关联的问题有关。 @Chris:怎么会这样?在a + b + c 中,关联性指定哪些操作数与哪些运算符相关联,但abc 可以按6 种可能的顺序中的任何一种进行评估。这对于评估变量没有太大区别,但请考虑 func1() + func2() + func3();这些函数可以按任何顺序调用。 @Keith - 我的大脑在别处。我仍然不明白为什么这个答案开始讨论评估顺序,但是当我读到我显然没有考虑“评估顺序”实际上是什么。

以上是关于为啥条件运算符是右结合的?的主要内容,如果未能解决你的问题,请参考以下文章

条件表达式,傻傻分不清楚

三目运算符

C语言中三目运算符是啥?

PHP中?:啥意思

Java表达式的执行顺序

为啥 return 语句会破坏条件运算符?