Reputation: 1344
In C-like languages, we are used to having if statements similar to the following:
if(x == 5) {
//do something
}
else if(x == 7) {
//do something else
}
else if(x == 9) {
//do something else
}
else {
//do something else
}
My question is, does the compiler see that if statement that way, or does it end up being interpreted like:
if(x == 5) {
//do something
}
else {
if(x == 7) {
//do something
}
else {
if(x == 9) {
//do something
}
else {
//do something else
}
}
}
I realized that while the question made sense in my head, it probably sounded rather stupid to the rest of the general populace. I was more referring to how the AST would look and if there was any special AST cases for 'else-if' statements or if it would be compiled as a cascading if/else block.
Upvotes: 17
Views: 6455
Reputation: 58568
Note that although your first statement is indented according to the if-else "ladder" convention, actually the "correct" indentation for it which reveals the true nesting is this:
if(x == 5) {
//do something
} else
if(x == 7) { // <- this is all one big statement
//do something else
} else
if(x == 9) { // <- so is this
//do something else
} else {
//do something else
}
Indentation is whitespace; it means nothing to the compiler. What you have after the first else
is one big if
statement. Since it is just one statement, it does not require braces around it. When you ask, "does the compiler read it that way", you have to remember that most space is insignificant; the syntax determines the true nesting of the syntax tree.
Upvotes: 1
Reputation: 8923
The two snippets of code are, in fact, identical. You can see why this is true by realizing that the syntax of the "if" statement is as follows:
if <expression>
<block>
else
<block>
NOTE that <block> may be surrounded by curly braces if necessary.
So, your code breaks down as follows.
// if <expression>
if (x == 5)
// <block> begin
{
//do something
}
// <block> end
// else
else
// <block> begin
if(x == 7) {
//do something else
}
else if(x == 9) {
//do something else
} else {
//do something else
}
// <block> end
Now if you put curly braces around the block for the "else", as is allowed by the language, you end up with your second form.
// if <expression>
if (x == 5)
// <block> begin
{
//do something
}
// <block> end
// else
else
// <block> begin
{
if(x == 7) {
//do something else
}
else if(x == 9) {
//do something else
} else {
//do something else
}
}
// <block> end
And if you do this repeatedly for all "if else" clauses, you end up with exactly your second form. The two pieces of code are exactly identical, and seen exactly the same way by the compiler.
Upvotes: 2
Reputation: 320421
In both C and C++ enclosing a statement into a redundant pair of {}
does not change the semantics of the program. This statement
a = b;
is equivalent to this one
{ a = b; }
is equivalent to this one
{{ a = b; }}
and to this one
{{{{{ a = b; }}}}}
Redundant {}
make absolutely no difference to the compiler.
In your example, the only difference between the first version and the second version is a bunch of redundant {}
you added to the latter, just like I did in my a = b
example above. Your redundant {}
change absolutely nothing. There's no appreciable difference between the two versions of code you presented, which makes your question essentially meaningless.
Either clarify your question, or correct the code, if you meant to ask about something else.
Upvotes: 12
Reputation: 2310
They are equivalent to a C compiler. There is no special syntax else if
in C. The second if
is just another if
statement.
To make it clearer, according to C99 standard, if statement is defined as
selection-statement:
if (expression) statement
if (expression) statement else statement
switch (expression) statement
and a compound-statement is defined as
compound-statement:
{block-item-list(opt) }
block-item-list:
block-item
block-item-list block-item
block-item:
declaration
statement
When a compiler frond-end tries to understand a source code file it often follows these steps:
The tree is then passed to compiler middle-end (to optimize) or back-end (to generate machine code)
In your case this if statement
if(x == 7) {
//do something else
} else if(x == 9) {
//do something else
} else {
//do something else
}
Is parsed as a selection-statement inside a selection-statement,
selection-stmt
/ | \
exp stmt stmt
| | |
... ... selection-stmt
/ | \
exp stmt stmt
| | |
... ... ...
and this one
if(x == 7) {
//do something else
} else {
if(x == 9) {
//do something else
} else {
//do something else
}
}
is the same selection-statement inside a compound-statement inside a selection-statement:
selection-stmt
/ | \
exp stmt stmt
| | |
... ... compound-stmt
|
block-item-list
|
block-item
|
stmt
|
selection-stmt
/ | \
exp stmt stmt
| | |
... ... ...
So they have different ASTs. But it makes no differences for the compiler backend: as you can see in the AST, there is no structural changes.
Upvotes: 19
Reputation: 78439
Closer to the first one, but the question doesn't exactly fit.
When a programs compiled, it goes through a few stages. The first stage is lexical analysis, then the second stage is syntactic analysis. Lexical analysis analyses the text, separating it into tokens. Then syntactic analysis looks at the structure of the program, and constructs an abstract syntax tree (AST). This is the underlying syntactic structure that's created during a compilation.
So basically, if and if-else and if-elseif-else statements are all eventually structures into an abstract syntax tree (AST) by the compiler.
Here's the wikipedia page on ASTs: https://en.wikipedia.org/wiki/Abstract_syntax_tree
edit: And actually, and if/if else statement probably forms something closer to the second one inside the AST. I'm not quite sure, but I wouldn't be surprised if its represented at an underlying level as a binary tree-like conditional branching structure. If you're interested in learning more in depth about it, you can do some research on the parsing aspect of compiler theory.
Upvotes: 0