C/C++ 三元运算符实际上是不是具有与赋值运算符相同的优先级?
Posted
技术标签:
【中文标题】C/C++ 三元运算符实际上是不是具有与赋值运算符相同的优先级?【英文标题】:Does the C/C++ ternary operator actually have the same precedence as assignment operators?C/C++ 三元运算符实际上是否具有与赋值运算符相同的优先级? 【发布时间】:2012-11-11 00:18:41 【问题描述】:我查阅过的几乎所有 C/C++ 运算符优先级表都将三元条件运算符列为比赋值运算符具有更高的优先级。然而,有几个表,例如wikipedia 上的一个和operator-precedence.com 上的一个,将它们置于相同的优先级。它是哪个,更高还是相同?
【问题讨论】:
【参考方案1】:在 C++ 语法中,
赋值表达式: 条件表达式 逻辑或表达式赋值运算符初始化子句 抛出表达式 条件表达式: 逻辑或表达式 逻辑或表达式?表达式:赋值表达式 初始化子句: 赋值表达式 支撑初始化列表可以合并为
赋值表达式: 逻辑或表达式 逻辑或表达式?表达式:赋值表达式 逻辑或表达式赋值运算符赋值表达式 逻辑或表达式赋值运算符初始化子句 抛出表达式如果只看=
和?:
,如果忽略?
和:
之间的内部表达式,这显然会赋予?:
和=
完全相同的优先级。
这与 C 语法不同,在 C 语法中,?:
的左操作数和右操作数都不能将赋值运算符作为其最顶层的运算符。
所以对于 C,给它们不同的优先级是有意义的。
也就是说,优先级只是标准实际所说的近似值,您选择的任何优先级都会显示这些级别具有误导性或完全错误。根据你的解释,?:
的内在表达可能是其中之一,它是给我的。
【讨论】:
在您的示例中,赋值是包含三元运算符表达式的子表达式。因此,优先级并不完全适用。 @MaximYegorushkin 是的,在a = b ? c : d
中,b ? c : d
是包含赋值表达式的子表达式,但都没有用括号指定。
@avakar 不,这在 C 中的含义与在 C++ 中的含义相同。不同的是a ? b : c = d
,但我在回答中避免了这一点:)
@hvd 你的回答如何证明什么?只有一种方法可以在表达式a ? b = c : d
中加上括号,所以第二个例子没用。第一个示例只是表明?
的优先级高于(或相同)=
。
@hvd 这对我来说似乎是一个全新的答案。您不应该将其作为新答案发布并恢复此答案以保留 cmets 的相关性吗?【参考方案2】:
C++ 的答案是?:
和=
具有相同的优先级。是的,几乎所有的 C++ 运算符优先级表都是错误的。
在 C 中,?:
是否高于 =
并不重要,因为在 C 中,?:
运算符不允许计算为左值,这是它必须做的如果优先级会影响行为(假设它们已经是 RTL 关联的)。例如,请参阅 Luchian Crigore 的回答下的讨论。
也许这个错误是如此普遍,因为早期的 C++ 运算符优先表可能是从 C 表中复制和扩展的。也许错误一直存在,因为唯一的反例——a?b:c=d
形式的表达式——很少使用。也许吧。
【讨论】:
【参考方案3】:你会发现,在标准中:
5 个表达式 [expr]
58) 运算符的优先级不是直接指定的,但可以从语法中推导出来。 (注)
这意味着优先表是推断的,而不是指定的。只要他们的行为相同,你就可以说两者都是对的。因此,即使优先表将它们设置为具有相同的优先级,或者将三元放在赋值运算符之上,实际上也会发生同样的事情,因为语法。
请注意,associativity 在这里发挥了更大的作用(这也源于语法)。
即使您假设它们具有相同的优先级:
a = b ? c : d;
将被视为a = (b ? c : d)
,因为它们都是从右到左关联的。
【讨论】:
正确,但优先级仍会影响a?b:c=d
的解释。是(a?b:c)=d
还是a?b:(c=d)
?
@IsakduPreez 它从右到左分组,所以a?b:(c=d)
。我已经说过在这种情况下关联性更重要。
通过说“关联性更重要”,您一定是在说“它们具有相同的优先级”,对吧?否则它将被解释为(a?b:c)=d
。
@IsakduPreez 你可以这样看,是的:)
这是不正确的解释,关联性只有在优先级相同时才有效。它不能“更重要”或扮演“更大的角色”以上是关于C/C++ 三元运算符实际上是不是具有与赋值运算符相同的优先级?的主要内容,如果未能解决你的问题,请参考以下文章