7

One of my university colleagues, who has started programming this year, sometimes writes if statements like this:

if(something) doA();
else
    if(something2) doC();
    else doD();

He is conviced that the second if-else pair is treated as a single entity, and that it is in fact nested under the first else.

I'm, however, sure that his code is equivalent to:

if(something) doA();
else if(something2) doC();
else doD();

This shows that the second else is not actually nested, but on the same level as the first if. I told him he needs to use curly braces to achieve what he wants to.

"But my code works as intended!"

And indeed, it worked as intended. Turns out the behavior of the code was the same, even if the else was not nested.

Surprisingly, I have found myself unable to write a clear and concise example that shows different behavior between

if(something) doA();
else
    if(something2) doC();
    else doD();

and

if(something) doA();
else {
    if(something2) doC();
    else doD();
}

Can you help me find an example that will show my colleague the difference between using/not using curly braces?

Or is the incorrect-looking version always equivalent to the one with curly braces, in terms of behavior?

Vittorio Romeo
  • 90,666
  • 33
  • 258
  • 416
  • 8
    He's right, you're wrong. The `else` controls a single statement. Curly braces are just a way to make a group of statements act (syntactically) like a single statement. If you only want it to control a single statement, the curly braces normally accomplish nothing. That said, you're usually better off placing an `else if` without further indentation. In C++, indentation does not affect behavior of code. – Jerry Coffin Jan 13 '14 at 16:58
  • 4
    you are both wrong, for different reasons. – yngccc Jan 13 '14 at 16:58
  • 1
    A trailing else without an if is a syntax error and your language will (usually) let you know that. So if the second if else statement was not treated together, you would essentially have if else else, not being syntactically correct. i.e. if you had if else{ if } else, this would be an error. – C.B. Jan 13 '14 at 17:00
  • 1
    in both cases if(something2 = false), doD() statement gets executed, and if(something=true) only DoA() is executed, so it's pretty much the same. – tesseract Jan 13 '14 at 17:04
  • @alk: No dangling else here. – Ben Voigt Jan 13 '14 at 17:08
  • This question already answered at http://stackoverflow.com/questions/2125066/is-it-bad-practice-to-use-an-if-statement-without-brackets – dinomoth Jan 13 '14 at 17:10
  • this question already answered at this [link][1] [1]: http://stackoverflow.com/questions/2125066/is-it-bad-practice-to-use-an-if-statement-without-brackets – dinomoth Jan 13 '14 at 17:12
  • Stop writing code like this. *You* will be its victim in the future. – JimR Jan 13 '14 at 17:15
  • Thanks for the comments. Guess there's always more to learn! I've always written code interpreting `if-else`s as in my second code snippet. Anyway, I apologized to my colleague and told him he was right all along! :) – Vittorio Romeo Jan 13 '14 at 17:16
  • @VittorioRomeo: The second code snippet is mathematically identical to the first; you could define a grammar and semantics in which `else if` was parsed as a statement after an `if` and the effect were the same as standard C. It is simply not the way C defines it. – Eric Postpischil Jan 13 '14 at 17:22
  • @EricPostpischil: That's what tricked me. I was so sure I was right because in all my years of programming I've always interpreted my `if-else` structures as in the second code snippet. – Vittorio Romeo Jan 13 '14 at 17:28
  • Braces are pretty expensive, it seems. – devnull Jan 13 '14 at 19:10

2 Answers2

11

Per C 2011 6.8.4 1, the grammar for a selection-statement includes this production:

selection-statement: if ( expression ) statement else statement

Per 6.8 1, a production for statement is:

statement: selection-statement

Thus, in:

if(something) doA();
else
    if(something2) doC();
    else doD();

the indented if and else form a selection-statement that is the statement that appears in the else clause of the preceding selection-statement.

The productions I have shown show that this is a possible interpretation in the C grammar. To see that it is the only interpretation, we observe that the text in the else clause of the initial selection-statement must be a statement, because there is no other production in the C grammar that produces an else keyword. (This is most easily seen by searching the grammar in clause A.2. Due to its size, I will not reproduce it here.) So we know the else is followed by a statement. We can easily see that the statement is a selection-statement, since it begins with if. Then the only question remaining is whether the next else is part of that if statement or not. Per 6.8.4.1 3, “An else is associated with the lexically nearest preceding if that is allowed by the syntax.”

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • 1
    Thanks for the quote from the Standard. I apologized to my colleague and told him he was right all along! :) – Vittorio Romeo Jan 13 '14 at 17:15
  • 2
    @VittorioRomeo Well, he is and he isn't. His indentation does reflect how the compiler sees things, but not how humans understand them. His indentation is bad programming practice. – James Kanze Jan 13 '14 at 17:57
  • The way your colleague writes code is wrong, because it is error prone. It is good for scientific interest that you found out what the code actually does, now you should tell him to always write conditionals using brackets. – Daniel Daranas Jan 13 '14 at 18:05
  • 1
    @JamesKanze: I have not seen any study that would justify a dogmatic statement of style or of human perception in this. Sometimes ifs and elses are used in testing a chain of conditions, and aligning them portrays that. Sometimes ifs and elses are used in testing nested conditions, an indenting them portrays them. – Eric Postpischil Jan 13 '14 at 20:03
  • @EricPostpischil Which is more or less what I'm saying (or meaning to say). When there is a chain of conditions, the `else if` should all be aligned, regardless of how the compiler views them. Indentation is communication of intent to other human beings. – James Kanze Jan 14 '14 at 11:18
5

Both structures come out to the same thing. The compiler effectively sees the code as:

if ( something ) {
    doA()
} else {
    if ( something2 ) {
        doC();
    } else {
        doD();
    }
}

In practice, however, there is no different between this and:

if ( something ) {
    doA();
} else if ( something2 ) {
    doC();
} else {
    doD();
}

The extra braces encapsulate a single statement, and you don't actually need the braces when the if or the else controls a single statement. (My first example puts every statement except the encompassing if in braces.)

Logically, programmers tend to thing along the lines of the second; languages where some sort of bracing ({}, BEGIN/END or indentation) is required almost always add an elsif or elif keyword in order to permit this second form. C and C++ (and Java, and C#, and...) don't, because the second form works out without the extra keyword.

In the end, you don't want the extra indentation. (I've cases with fifteen or twenty successive else if. That would make for some serious indentation.) On the other hand, you do want the controlled statement on a separate line. (Bracing is optional: if your coding standard puts the brace on a separate line, it's also conventional to suppress it if it only contains a single statement.)

James Kanze
  • 150,581
  • 18
  • 184
  • 329