1. 8
  1. 4

    GCC and Clang have an available warning for when you combine some operators that are common causes of precedence bugs — I think one example is == and &. It’ll nag you to add parens to make your intentions clear. I’m pretty sure this is one of the warnings included with -Wall.

    Yet another good reason to turn on lots of warnings plus -Werror! In fact I’ve taken to opting out of warnings, not in — I include a canned file in my build system (XcodeWarnings.xcconfig) that turns on nearly every available compiler warning, then I follow it with some lines to turn off specific warnings I don’t want.

    1. 4

      For a long time, I have used a style rule in my own code that says ‘any sequence containing two operators must be parenthesised’. This means that A op1 B op1 C op1 D is fine but A op1 B op2 C must be written as either (A op1 B) op2 C or A op1 (B op2 C), whichever is intended. Since I started following this rule, I have never had to think about operator precedence. It doesn’t matter if the sequence is unambiguous to the compiler, it must also be unambiguous to the reader. If the reader has some cognitive load from remembering precedence, then that is mental effort that they are not able to spend finding real bugs in my code.

      1. 2

        Parsing adjacent (( parentheses and matching them across expressions is also a cognitive load (yes, even if you colour the parentheses). So is having to figure out WHY someone put parentheses in their expression as usually that’s an indication that normal operator precedence wasn’t applicable. Adding parentheses is not zero cost for everyone and I only do it explicitly (in situations where default precedence would otherwise have conveyed the same meaning) when mixing && and || or where & or | are used within a larger expression.

        The same can be said about useless comments in code, when people comment something it draws the eye and makes the reader pay special attention, when the comments are literally just a translation of the code into English this puts unnecessary cognitive strain on the reader.

        1. 0

          Parsing adjacent (( parentheses and matching them across expressions is also a cognitive load (yes, even if you colour the parentheses)

          Fortunately, most people reading my code use a visual cortex that evolved to recognise predators that have bilateral symmetry. As such, they can offload matching parentheses to some dedicated processing before it reaches their conscious mind.

      2. 2

        I’m not a fan of -Werror. I like compiling with -std=c99 -pedantic and there are a few POSIX features that run afoul of that. For example, “ISO C forbids assignment between function pointer and `void *’”, but POSIX requires that.

        1. 1

          What’s an example of POSIX requiring it? AFAIK that assignment is undefined behaviour.

          1. 2

            Since POSIX specifies the functions, such as dlopen, commonly found in dlfcn.h, and dlopen returns a void * it is therefore required to work on a POSIX compliant system. I think the standard calls it out explicitly somewhere but you’ll have to do your own legwork there.

            1. 1

              After a sleep I noticed the mistake, it’s dlsym that matters not dlopen but the point still stands.

          2. 1

            Better IMHO to leave -Werror on but turn off the specific warning(s) you don’t like. The warning message includes the name of the flag that controls it.

        2. 3

          This has some weird bugs. The precedence of a(b) >> c &= d is definitely not (a(b)) >> (c &= d), it is (((a(b)) >> c) &= d) (which is invalid in C as you can’t assign to an expression). The precedence of a *= b != c ? d : e is not ((a *= (b != c)) ? d : e), it is (a *= ((b != c) ? d : e)). There seems to be some issues with this game’s understanding of the precedence of assignment operators and also the associativity of comparison operators.

          1. 1

            Perhaps this is a bug in Tree-sitter? You can see the AST it makes here.


            Edit: Reported: https://github.com/tree-sitter/tree-sitter-c/issues/101

          2. 1

            your “correct” sound is very loud

            please add a volume slider (which is both nice to adjust and serves as a warning that there is sound)