Damon Swayn
Damon Swayn

Reputation: 1344

how does a C-like compiler interpret the if statement

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

Answers (5)

Kaz
Kaz

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

Ziffusion
Ziffusion

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

AnT stands with Russia
AnT stands with Russia

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

Naruil
Naruil

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:

  1. Lexical analysis: turn the plain-text source code into a list of 'tokens'
  2. Semantic analysis: parse the token list and generate an abstract syntax tree (AST)

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

Nathan
Nathan

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

Related Questions