Which operator(s) in C have wrong precedence?

前端 未结 4 2089
面向向阳花
面向向阳花 2021-02-08 07:17

In the \"Introduction\" section of K&R C (2E) there is this paragraph:

C, like any other language, has its blemishes. Some of the operators h

相关标签:
4条回答
  • 2021-02-08 07:44

    It depends which precedence convention is considered "correct". There's no law of physics (or of the land) requiring precedence to be a certain way; it's evolved through practice over time.

    In mathematics, operator precedence is usually taken as "BODMAS" (Brackets, Order, Division, Multiplication, Addition, Subtraction). Brackets come first and Subtraction comes last.Ordering Mathematical Operations | BODMAS Order of operations

    Operator precedence in programming requires more rules as there are more operators, but you can distil out how it compares to BODMAS.

    The ANSI C precedence scheme is pictured here:

    As you can see, Unary Addition and Subtraction are at level 2 - ABOVE Multiplication and Division in level 3. This can be confusing to a mathematician on a superficial reading, as can precedence around suffix/postfix increment and decrement.

    To that extent, it is ALWAYS worth considering adding brackets in your mathematical code - even where syntactically unnecessary - to make sure to a HUMAN reader that your intention is clear. You lose nothing by doing it (although you might get flamed a bit by an uptight code reviewer, in which you can flame back about coding risk management). You might lose readability, but intention is always more important when debugging.

    And yes, the link you provide is a good example. Countless expensive production errors have resulted from this.

    0 讨论(0)
  • 2021-02-08 07:47

    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 >=.

    0 讨论(0)
  • 2021-02-08 08:02

    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

    0 讨论(0)
  • 2021-02-08 08:02

    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?
    0 讨论(0)
提交回复
热议问题