Search code examples
cif-statementgccclangcompiler-warnings

Why does "dangling-else" emit a warning?


I have a program. Somewhere in the program, I have this code:

int
read_n(char *cp, int n)
{
  int nread;
  if ((nread = read(STDIN_FILENO, cp, n)) != n)
    if (nread == -1)
      die(DIE_ERROR_FMT, "failed reading input");
    else
      return nread;
  return n;
}

and compiling my program like this:

cc -std=c99 -Wall -Wextra -Wshadow -Wpedantic prog.c -o prog

I get:

le.c:343:5: warning: add explicit braces to avoid dangling else [-Wdangling-else]

Why exactly is this a warning, and necessary? I know that the else goes to the nearest else-less if and prefer to avoid braces when possible (for readability). This is clang, gcc gives a similar error.


Solution

  • Indentation doesn't matter in C. Each of the following is exactly identical:

    if a()
    if b()
    foo();
    else
    bar();
    

    and

    if (a)
      if (b)
        foo();
      else
        bar();
    

    and

    if (a)
      if (b)
        foo();
    else
      bar();
    

    The compiler is warning you that this appears ambiguous to humans, and you should explicitly add braces to make your code obvious.


    Edit: As noted in a comment, my answer makes it clear that indentation doesn't matter, and doesn't help disambiguate which if the else was intended to belong to.

    It's worth mentioning that it's not only leading indentation but all whitespace that doesn't matter. C (and most languages based on C syntax) makes no difference between spaces, tabs, and newlines.

    Here are a few more versions that are exactly identical to the above versions:

    if (a) if (b) foo(); else bar();
    
    if (a)
      if (b) foo(); else bar();
    
    if (a)
      if (b) foo();
    else bar();
    

    Again, there is no ambiguity for the compiler here, but many humans will struggle to understand where the else goes.