Confusion between '=' and '==' is a typical pain point that beginners have when learning to program. Plus it is super at odds with the notation we all learn in math.
':=' is didactically better because it shows that assignment has an direction. It also leaves '=' for actual equality.
The only operators with precedence between & and && are ^ and |, though. In e.g. the expression from the sibling comment, `a & b == c`, writing & or && doesn't make any difference (aside from short-circuiting). I guess it's an issue if you write & instead of && in an expression that also involves a bitwise-OR (or | instead of || in an expression that also involves logical-AND), but that seems quite rare. I expect that reversing the precedence of the bitwise and logical operators would create problems a lot more often.
The reason that & and | have lower precedence than the comparison operators is indeed historical - it's because the earliest versions of the language didn't have the logical boolean operators && and ||, so the bitwise & and | operators stood in for them. The lower precedence meant that you could write:
if (x == 1 & y == 2) {
..and have it do what you meant. This became a bit of a wart when the && and || operators were introduced (still well before ANSI standardisation), but it was considered that changing it would have broken too much existing code.
> However, the precedence of & vs &&, or & vs ||, etc is a source of problems.
Do you have any examples of this? In my experience you almost always want the bitwise operators to have a higher precedence than the logical operators, as using the result of logical operators as a bitmask makes little sense. Consider e.g. `A & B && C & D`, which currently is equivalent to `(A & B) && (C & D)`, but with reversed precedence would be equivalent to the almost nonsensical `A & (B && C) & D`.
Now, the precedence of == with respect to & and | is actually problematic (as Ritchie admits as well). Having `A == B | C` interpreted as `(A == B) | C` is almost never desirable. For extra annoyance, the shift operators do have higher precedence than comparison, so `A == B << C` does what you usually want (`A == (B << C)`).
That looks a lot like the old Pascal assignment vs equivalence operators. In Pascal (read Delphi) we had '=' for equality and ':=' for assignment. So:
x = 5 <-- a boolean statement, true if x equ 5
x := 5 <-- an assignment of the value 5 to the var x.
TBH, it's only like '=' vs '==' in C like languages. But it's easier to spot errors, as Pascal can never have a valid statement where the two are used in the wrong way.
I interpreted GP's comment as asking what the precedence of == was (assumably in C, given that we're discussing a post by Dennis Ritchie). On second read it could also be interpreted as asking what a good precedence for == would be, in which case you're absolutely right. Sorry about that.
> Not sure why I'd want this: (flags & (4 == 4)), but that's what flags & 4 == 4 does.
Originally there was no && operator. You had to use & for Boolean conjunction too. The precedence makes sense under that condition. (And later couldn't be changed without breaking existing code.)
reply