&&优先于||
据我所知,逻辑运算符&&
优先级高于||
。 在运行代码:
#include <stdio.h> int main() { int i = 1, j =1, k = 1; printf("%d\n",++i || ++j && ++k); printf("%d %d %d",i,j,k); return 0; }
正在给出的输出:
1 2 1 1
这只有在++i || ++j && ++k
时才有可能 ++i || ++j && ++k
是这样评估的:
(++i) || (++j && ++k)
但是,根据运营商的优先规则,它应该被评估为:
(++i || ++j) && (++k)
因此产出应该是:
1 2 1 2
这是怎么回事?
注:根据我的理解,我认为更高优先级的运算符评估如下( 如果它是左联合的 ):
评估它的左边的expression
2.然后评估其正确的expression(如果需要)
我错了吗?
你说:
这只有在
++i || ++j && ++k
时才有可能++i || ++j && ++k
是这样评估的:(++i) || (++j && ++k)
但是,根据运营商的优先规则,它应该被评估为:
(++i || ++j) && (++k)
第一个分组是正确的,因为&&
的优先级高于||
的优先级 。 然后整个expression式评估||
的LHS ,增加i
的副作用,评估为真。 这意味着||
的RHS ( &&
expression式)根本不被评估,因为不需要确定整个expression式的真实性。
所以,编译器是正确的; 你以某种方式误解了优先权。
为什么第一个分组是正确的? 根据第一个分组
||
比&&
具有更高的优先级。 我怎么了?
你看不懂优先顺序,或者你不了解优先顺序与评估顺序的相互作用。 第一个分组给了&&
更高的优先级。
如果你有a + b * c
,其中*
的优先级高于+
,那么它被评估为a + (b * c)
,不是吗? 将+
更改为||
和*
到&&
和expression式是同构的和解释是相似的。
算术expression式和逻辑expression式的区别在于,逻辑expression式的操作数必须从左到右进行计算,但是算术expression式的操作数不要; 编译器可以在评估之前评估b * c
(但在添加之前必须评估b * c
)。 相比之下,在逻辑expression式( a || b && c
)中,编译器必须在评估b && c
之前评估b && c
,并且当a
变为true时,它不能评估b
或c
,更不用说b && c
。
||
运算符短路 – 如果其第一个操作数的计算结果为真(非零),则不计算其第二个操作数。
&&
也是如此,如果第一个操作数是假的,它不使用它的第二个操作数。 这是一个可能的优化,因为任何布尔值OR true都是true,同样,任何布尔值AND false都是false。
好的,所以你把评估顺序搞混了。 这里什么都不是矛盾的:
++i || ++j && ++k
被分组为
(++i) || (++j && ++k)
因为&&
具有更高的优先级。 但是这个OR操作的LHS是真的,所以整个RHS和它的AND操作都被丢弃了,没有被评估。
在编辑中给你留意:是的,你错了:运算符优先级与评估顺序依然不一样。 这只是分组。
首先,如你自己所说的, &&
具有更高的优先级,这意味着操作数分组应该是
(++i) || (++j && ++k)
为什么你说“根据运算符优先级”应该是(++i || ++j) && (++k)
对我来说是不清楚的。 这只是与你自己说的相矛盾。
其次,运营商的优先级与评估的顺序完全没有关系。 运算符优先级决定了运算符和它们的操作数之间的分组 (即运算符优先级说哪个运算符属于哪个运算符)。
同时, 评价顺序是一个完全不同的故事。 它要么保持不明确,要么由完全不同的规则来定义。 在||
情况下 和&&
操作员的评估顺序的确定义是从左到右(尽可能强制提前完成)。
所以,运营商优先规则告诉你,分组应该是
(++i) || ((++j) && (++k))
现在,评估顺序规则告诉你,首先我们评估++i
,然后(如果需要的话)评估++j
,然后(如果需要的话)评估++k
,然后评估&&
最后评估||
。
由于您误解了优先级,我们试着用一个math例子来清除它。 乘法和除法的优先级高于加法和减法。 这意味着这个expression式:
a + b * c - d / e
可以这样写:
a + (b * c) - (d / e)
既然你正确地表示&&
比||
有更高的优先级 ,这个expression式:
i || j && k
可以这样写:
i || (j && k)
你可以把它看作是“优先级最高的操作首先加括号”,如果有帮助的话。
(但优先次序与评估有所不同 – 如果i
是真的,那么(j && k)
永远不会被评估。)