Which operator(s) in C have wrong precedence?
Yes, the situation discussed in the message you link to is the primary gripe with the precedence of operators in C.
Historically, C developed without &&
. To perform a logical AND operation, people would use the bitwise AND, so a==b AND c==d
would be expressed with a==b & c==d
. To facilitate this, ==
had higher precedence than &
. Although &&
was added to the language later, &
was stuck with its precedence below ==
.
In general, people might like to write expressions such as (x&y) == 1
much more often than x & (y==1)
. So it would be nicer if &
had higher precedence than ==
. Hence people are dissatisfied with this aspect of C operator precedence.
This applies generally to &
, ^
, and |
having lower precedence than ==
, !=
, <
, >
, <=
, and >=
.
There is a clear rule of precedence that is incontrovertible. The rule is so clear that for a strongly typed system (think Pascal) the wrong precedence would give clear unambiguous syntax errors at compile time. The problem with C is that since its type system is laissez faire the errors turn out to be more logical errors resulting in bugs rather than errors catch-able at compile time.
The Rule
Let ○ □ be two operators with type
○ : α × α → β
□ : β × β → γ
and α and γ are distinct types.
Then
x ○ y □ z can only mean (x ○ y) □ z, with type assignment
x: α, y : α, z : β
whereas x ○ (y □ z) would be a type error because ○ can only take an α whereas the right sub-expression can only produce a γ which is not α
Now lets
Apply this to C
For the most part C gets it right
(==) : number × number → boolean
(&&) : boolean × boolean → boolean
so && should be below == and it is so
Likewise
(+) : number × number → number
(==) : number × number → boolean
and so (+) must be above (==) which is once again correct
However in the case of bitwise operators
the &/| of two bit-patterns aka numbers produce a number
ie
(&), (|) : number × number → number
(==) : number × number → boolean
And so a typical mask query eg. x & 0x777 == 0x777
can only make sense if (&) is treated as an arithmetic operator ie above (==)
C puts it below which in light of the above type rules is wrong
Of course Ive expressed the above in terms of math/type-inference
In more pragmatic C terms x & 0x777 == 0x777
naturally groups as
x & (0x777 == 0x777)
(in the absence of explicit parenthesis)
When can such a grouping have a legitimate use?
I (personally) dont believe there is any
IOW Dennis Ritchie's informal statement that these precedences are wrong can be given a more formal justification
Wrong may sound a bit too harsh. Normal people generally only care about the basic operators like +-*/^
and if those don't work like how they write in math, that may be called wrong. Fortunately those are "in order" in C (except power operator which doesn't exist)
However there are some other operators that might not work as many people expect. For example the bitwise operators have lower precedence than comparison operators, which was already mentioned by Eric Postpischil. That's less convenient but still not quite "wrong" because there wasn't any defined standard for them before. They've just been invented in the last century during the advent of computers
Another example is the shift operators << >>
which have lower precedence than +-
. Shifting is thought as multiplication and division, so people may expect that it should be at a higher level than +-
. Writing x << a + b
may make many people think that it's x*2a + b until they look at the precedence table. Besides (x << 2) + (x << 4) + (y << 6)
is also less convenient than simple additions without parentheses
In other languages there are many real examples of "wrong" precedence
- One example is T-SQL where
-100/-100*10 = 0
- PHP with the wrong associativity of ternary operators
- Excel with wrong precedence (lower than unary minus) and associativity (left-to-right instead of right-to-left) of
^
:- According to Excel, 4^3^2 = (4^3)^2. Is this really the standard mathematical convention for the order of exponentiation?
- Why does =-x^2+x for x=3 in Excel result in 12 instead of -6?
- Why is it that Microsoft Excel says that 8^(-1^(-8^7))) = 8 instead of 1/8?