按位运算符优先级

3

我在类C语言中遇到的一个问题是:

original | included & ~excluded   // BAD

由于优先级问题,这将被解析为:

original | (included & ~excluded)   // '~excluded' has no effect

有人知道为什么在初始设计时选择了三个不同的优先级别来处理位运算符吗?更重要的是,您是否认同这种决策,以及原因是什么?

2个回答

7

这些运算符自C以来就具有这种优先级。

我同意这个顺序,因为它与它们最相似的算术运算符的相对顺序相同(+*和否定)。

你可以在这里看到 &* 的相似性,以及 |+ 的相似性:

A  B | A&B A*B | A|B A+B 
0  0 |  0   0  |  0   0
0  1 |  0   0  |  1   1
1  0 |  0   0  |  1   1
1  1 |  1   1  |  1   2

通过以下公式可以看出按位取反和否定的相似性:

~A = -A - 1

3
你可以注意到 ^* 下面、在 | 上面,这有点随意但也是合理的。不幸的是,在 C 语言中,二进制位运算符的优先级比比较运算符低,因此需要像 (status & MASK) != MASK 这样的表达式来要求额外的括号。 - RBerteig
1
这一切都很有道理,除了分配律也逆向成立:A|B & A|C == A | (B&C)。但我会说按位运算的用例与布尔运算的用例远远不同(其优先级对我来说非常合理)。你会看不起一个将所有按位运算符优先级定义为相同的语言吗?(为什么?) - zildjohn01
@zildjohn01:好观点,我已经去掉了分散性。关于你的问题——我会看不起这种语言吗?我会发现它非常不直观,但是添加额外的括号很少会使代码不可读,所以如果我知道它(我可能会通过编写不起作用的代码并进行调试来学习),那么这不会是一个很大的问题。如果一种语言使用不合逻辑(在我看来)的优先级,则我会立即保持警惕,想知道我可能会在该语言中遇到什么其他“问题”。这与最少惊讶原则有关。 - Mark Byers
你用 POLA 说服了我。有时候很难区分哪些更改是可以接受的(例如 @RBerteig 提到的),哪些更改太过了。 - zildjohn01
1
@zildjohn01,我从未尝试过弄清楚位运算和比较之间优先级反转的原理。我认为一定有一个原因,因为即使是第一版K&R也将其称为错误的来源。当然,在那时已经太晚了,而且三十年后修复它已经太晚了。在我看来,如果一种语言“足够类似于C”,那么它的运算符应该遵循C的优先级,否则你会冲突。当然,我不确定我所说的“足够”是什么意思。 - RBerteig
显示剩余2条评论

1
为了扩展Mark Byers的答案,在布尔代数中(电气工程师广泛使用它来简化逻辑电路到最少数量的门并避免竞争条件),传统是按位AND优先于按位OR。C语言只是遵循这个既定的传统。请参见http://en.wikiversity.org/wiki/Boolean_algebra#Combining_Operations

就像在普通代数中,乘法优先于加法一样,AND优先(或优先)于OR。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接