• Operator Precedence

    From Lawrence D'Oliveiro@21:1/5 to All on Tue Feb 6 01:24:36 2024
    Operator precedence in C, particularly in regard to the bitwise operators,
    can be a bit awkward. Consider an expression like

    (val & check_bits) == set_bits

    which uses “check_bits” to mask out the bits to check from “val”, and then
    compares the result to “set_bits”. A more natural precedence order would allow this to be written without the parentheses:

    val & check_bits == set_bits

    I discovered a few years ago (quite by accident) that Python does make a
    small change to the operator precedences to allow exactly this sort of
    thing.

    My question is, if this corresponding operator precedence change were to
    be made in C, is there any actual real-world code that would break?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to Lawrence D'Oliveiro on Tue Feb 6 02:01:56 2024
    On 2024-02-06, Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
    Operator precedence in C, particularly in regard to the bitwise operators, can be a bit awkward. Consider an expression like

    (val & check_bits) == set_bits

    Yes, this is famous. It's because the bitwise & was used for combining
    Boolean conditions, before && was introduced:

    if (foo > 0 & odd(bar)) { ... }

    In a 1982 e-mail, Dennis Ritchie wrote:

    "In retrospect it would have been better to go ahead and change the
    precedence of & to higher than ==, but it seemed safer just to split &
    and && without moving & past an existing operator. (After all, we had
    several hundred kilobytes of source code, and maybe 3 installations....)"

    That's it. 600 kilobytes of code being preserved is why we can't have

    val & check_bits == set_bits

    and whatnot.

    My question is, if this corresponding operator precedence change were to
    be made in C, is there any actual real-world code that would break?

    Yes; anything that does

    some_condition & variable == TEST_VALUE

    where && could have been used, but wasn't. Perhaps due to a typo;
    but the code is tested and works since some_condition has the values
    0 and 1.

    A good time to fix it was when Dennis Ritchie and gang had 600 kilobytes
    of code in 3 installations.

    Yet, I think the situation could be repaired with a carefully
    rolled-out plan.

    Firstly, require all ambiguous uses of & to be parenthesized, so
    that code like condition & variable == TEST_VALUE requires a diagnostic;
    it has to be condition & (variable == TEST_VALUE) or
    (condition & variable) == TEST_VALUE.

    Then after a long period of obsolescence, remove the requirement for parentheses, and introduce the new precedence for & and |.

    By the time the obsolescence period is over, most old code still in use
    would have been fixed to have the required parentheses. Those are now
    optional; new code can start using the nicer new precedence.

    Then any remaining broken old code can still be supported with old
    dialect modes, like "gcc -std=c17" or lower.

    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Keith Thompson on Tue Feb 6 02:54:31 2024
    On Mon, 05 Feb 2024 18:33:56 -0800, Keith Thompson wrote:

    But not everyone does write it with the parentheses.

    Let us be clear about what we are talking about. You are suggesting that
    people write an expression like

    a «bitop» b «cmp» c

    with the expectation that it means

    a «bitop» (b «cmp» c)

    because currently in C, anybody who wants it to mean

    (a «bitop» b) «cmp» c

    has to write it that way, with explicit parentheses, anyway.

    The question is, who would write something like (with or without
    parentheses)

    a «bitop» (b «cmp» c)

    and why? Because a comparison in C only returns either 0 or 1, while bit operators are most useful dealing with multibit masks.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Malcolm McLean on Tue Feb 6 02:26:36 2024
    On Tue, 6 Feb 2024 01:37:54 +0000, Malcolm McLean wrote:

    On 06/02/2024 01:24, Lawrence D'Oliveiro wrote:

    My question is, if this corresponding operator precedence change were
    to
    be made in C, is there any actual real-world code that would break?

    Yes tons of it. Badly written code because in any sensible coding
    standard you must have the parentheses.

    Given that everybody has to write it with the parentheses in existing
    code, changing the operator precedence will not affect the correctness of
    such expressions.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to Lawrence D'Oliveiro on Tue Feb 6 02:58:51 2024
    On 2024-02-06, Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
    On Mon, 05 Feb 2024 18:33:56 -0800, Keith Thompson wrote:

    But not everyone does write it with the parentheses.

    Let us be clear about what we are talking about. You are suggesting that people write an expression like

    a «bitop» b «cmp» c

    with the expectation that it means

    a «bitop» (b «cmp» c)

    The problem is that this is what it means that regardless of anyone's expectation.

    The question is, who would write something like (with or without
    parentheses)

    a «bitop» (b «cmp» c)

    For one thing, someone who writes & instead of &&, or | instead of ||,
    as a pure typo, and the operands happen to be in the {0, 1} domain so
    that it works fine.

    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Lew Pitcher on Tue Feb 6 03:05:40 2024
    On Tue, 6 Feb 2024 03:01:18 -0000 (UTC), Lew Pitcher wrote:

    Given that
    v_a & v_b == v_c
    is a valid expression that binary ANDs v_a with the truth value of the expression (v_b == v_c), your proposed change in operator precedence
    would greatly affect the correctness of the expression.

    That’s why I asked for “real-world” examples. Why would anyone want to write such an expression with the bitwise operators, instead of using the boolean ones?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lew Pitcher@21:1/5 to Lawrence D'Oliveiro on Tue Feb 6 03:01:18 2024
    On Tue, 06 Feb 2024 02:26:36 +0000, Lawrence D'Oliveiro wrote:

    On Tue, 6 Feb 2024 01:37:54 +0000, Malcolm McLean wrote:

    On 06/02/2024 01:24, Lawrence D'Oliveiro wrote:

    My question is, if this corresponding operator precedence change were
    to
    be made in C, is there any actual real-world code that would break?

    Yes tons of it. Badly written code because in any sensible coding
    standard you must have the parentheses.

    Given that everybody has to write it with the parentheses in existing
    code, changing the operator precedence will not affect the correctness of such expressions.

    Given that
    v_a & v_b == v_c
    is a valid expression that binary ANDs v_a with the truth value of the expression (v_b == v_c), your proposed change in operator precedence would greatly affect the correctness of the expression.

    --
    Lew Pitcher
    "In Skills We Trust"

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lew Pitcher@21:1/5 to Lawrence D'Oliveiro on Tue Feb 6 04:48:56 2024
    On Tue, 06 Feb 2024 03:05:40 +0000, Lawrence D'Oliveiro wrote:

    On Tue, 6 Feb 2024 03:01:18 -0000 (UTC), Lew Pitcher wrote:

    Given that
    v_a & v_b == v_c
    is a valid expression that binary ANDs v_a with the truth value of the
    expression (v_b == v_c), your proposed change in operator precedence
    would greatly affect the correctness of the expression.

    That’s why I asked for “real-world” examples.

    While I have no "real world" examples to give you, I have no doubt
    that, somewhere in the hundreds of millions of lines of C code currently
    in use, there are examples of exactly this sort of code.

    Why would anyone want to
    write such an expression with the bitwise operators, instead of using the boolean ones?

    Because they can?
    Because it suits their needs?
    Because they don't know better?

    It doesn't matter. The C standard has, up until now, permitted such code,
    and so, somewhere, someone has written it. And, now, despite your preferences, it must be maintained.

    --
    Lew Pitcher
    "In Skills We Trust"

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Lawrence D'Oliveiro on Mon Feb 5 23:19:07 2024
    Lawrence D'Oliveiro <ldo@nz.invalid> writes:

    Operator precedence in C, particularly in regard to the bitwise operators, can be a bit awkward. Consider an expression like

    (val & check_bits) == set_bits

    which uses ?check_bits? to mask out the bits to check from ?val?, and then compares the result to ?set_bits?. A more natural precedence order would allow this to be written without the parentheses:

    val & check_bits == set_bits

    I discovered a few years ago (quite by accident) that Python does make a small change to the operator precedences to allow exactly this sort of
    thing.

    My question is, if this corresponding operator precedence change were to
    be made in C, is there any actual real-world code that would break?

    Surely the answer to that question is an emphatic yes, but in any
    case it's the wrong question.

    An obvious first question is, if such a change were made to C
    (via changes to the ISO C standard), would it result an any
    significant gain? The answer to that question is No. Some
    things would be easier, some things would be harder, the overall
    effect on programming effort might be a net positive, but it is
    as best a second-order effect: possibly a gain, but not a
    significant gain.

    An obvious next question is, if such a change were made to C, how
    much collateral damage would result? The answer to that question
    is hard to know exactly, but without doubt it is at least huge.
    Consider what happened with C99. For the most part C99 was upward
    compatible with C90, with two exceptions: removal of implicit
    function declarations, and removal of implicit int. Furthermore
    those changes would cause diagnostics if run on C90 code that
    didn't fit the C99 rules. Despite that it took a very long time,
    probably at least a decade, before C99 was fully embraced by the
    C community. The effect of a change in precedence relationships
    surely would be much, much longer. An important principle in the
    evolution of C is that working code keeps working. There are some
    exceptions to that principle, but they are rare and modest in
    scale. The proposed precedence change would not be an evolution
    of the language but a bifurcation of the language. In this case
    the "cure" is worse than the disease.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Lawrence D'Oliveiro on Tue Feb 6 10:59:10 2024
    On 06/02/2024 03:54, Lawrence D'Oliveiro wrote:
    On Mon, 05 Feb 2024 18:33:56 -0800, Keith Thompson wrote:

    But not everyone does write it with the parentheses.

    Let us be clear about what we are talking about. You are suggesting that people write an expression like

    a «bitop» b «cmp» c

    with the expectation that it means

    a «bitop» (b «cmp» c)

    because currently in C, anybody who wants it to mean

    (a «bitop» b) «cmp» c

    has to write it that way, with explicit parentheses, anyway.

    The question is, who would write something like (with or without
    parentheses)

    a «bitop» (b «cmp» c)

    and why? Because a comparison in C only returns either 0 or 1, while bit operators are most useful dealing with multibit masks.

    It's common to use && than & :

    x == 1 && y == 2

    People might use & rather than && because they want to avoid
    short-circuit evaluation, or because they think (usually wrongly, but
    sometimes people have to use weaker compilers) that it gives more
    efficient code. They may also write things like :

    if (x == true & y == true) ...

    I'm struggling to find an example where this kind of thing would be
    objectively good code, but people do write odd code. So yes, I think a
    change in the precedence /would/ cause breakage, but not a lot, and
    mostly in code that was a bit odd to start with. However, that's enough
    to put it out of the question for a change to C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)