当初学C语言的时候,我也曾经思考过这个问题,感觉位运算符的优先级应该在移位运算符(<< >>
)的和不等于运算符( < <= >= >
)这两类运算符之间更合适。可惜当时没能不求甚解,以为K&R两位大师这么做自有其玄妙,吾等凡人功力商浅不必参悟透彻。多年后,在StackOverflow上碰巧看到这个问题 Why do bitwise operators have lower priority than comparisons?,终于解答了我的疑惑。
Dennis M. Ritchie 大神的解答(The Development of the C Language):
Neonatal C
Rapid changes continued after the language had been named, for example the introduction of the && and || operators. In BCPL and B, the evaluation of expressions depends on context: within if and other conditional statements that compare an expression's value with zero, these languages place a special interpretation on the and (&) and or (|) operators. In ordinary contexts, they operate bitwise, but in the B statement
if (e1 & e2) ...
the compiler must evaluate e1 and if it is non-zero, evaluate e2, and if it too is non-zero, elaborate the statement dependent on the if. The requirement descends recursively on & and | operators within e1 and e2. The short-circuit semantics of the Boolean operators in such `truth-value' context seemed desirable, but the overloading of the operators was difficult to explain and use. At the suggestion of Alan Snyder, I introduced the && and || operators to make the mechanism more explicit. Their tardy introduction explains an infelicity of C's precedence rules. In B one writes
if (a==b & c) ...
to check whether a equals b and c is non-zero; in such a conditional expression it is better that & have lower precedence than ==. In converting from B to C, one wants to replace & by && in such a statement; to make the conversion less painful, we decided to keep the precedence of the & operator the same relative to ==, and merely split the precedence of && slightly from &. Today, it seems that it would have been preferable to move the relative precedences of & and ==, and thereby simplify a common C idiom: to test a masked value against another value, one must write
if ((a&mask) == b) ...
where the inner parentheses are required but easily forgotten.
简而言之,是两位大神掉进了自己挖的坑里了。C语言的前身是B语言。B语言是没有逻辑运算符(&& ||)的,是通过位运算充当逻辑运算的。大神在发明C时,沿用的B语言的一些~~陋习~~传统。由于C的流行,在C之后发明的大多数类C语言也纷纷掉这个坑里了。