A hazard of precedence

I encountered a bug recently from a precedence mistake. Someone had written if (a = b == c), intending if ((a = b) == c) - but in C == has higher precedence than =, so that wasn't how the parser saw it. The typechecker didn't object, because the result type of == in C is int, so all was apparently well. None of the humans noticed either, perhaps because b was a large expression, so the two infix operators were far apart.

Operator precedence saves lots of parentheses, but it does occasionally lead to bugs. It's one of the class of language features that work by resolving ambiguity, and these have a common hazard: when you don't notice the ambiguity, it will still be resolved, and not necessarily as you intend.

3 comments:

  1. Maybe there ought to be a warning for expressions that rely on the less-obvious precedence rules.

    In this case it would have been better style to say:

    a=b;
    if (a==c) {

    A warning recommending that change wouldn't ever be out of line, I don't think. It compiles to the same code as ((a=b)==c)

    ReplyDelete
  2. I don't know of any C compiler in common use that won't give a warning for the given example. Assignment expressions in predicate contexts like an if statement normally need at least an extra level of parenthesising to shut the compiler up.

    For example, gcc -Wall gives:

    warning: suggest parentheses around assignment used as truth value

    bcc32 gives:

    Possibly incorrect assignment in function main

    cl -Wall gives:

    warning C4706: assignment within conditional expression

    You aren't by any chance compiling with warnings disabled? I don't recommend that.

    ReplyDelete
  3. The compiler this was built with is ancient, and warnings are turned down because someone found them annoying. :) And it's not much use to turn the warnings back up, since that produces a flood of (hopefully) spurious ones from code I don't have free rein to clean up. But that's another story...

    I did move the assignment out of the if, of course. But that's a mundane problem. The more interesting one of overlooked ambiguity doesn't depend on those particular operators - it can happen with arithmetic, though perhaps less easily, since people are used to noticing precedence in arithmetic expressions.

    ReplyDelete

It's OK to comment on old posts.