类C编译器如何解释if语句

6psbrbz9  于 2023-06-21  发布在  其他
关注(0)|答案(5)|浏览(125)

在类C语言中,我们习惯于使用类似于以下内容的if语句:

if(x == 5) {
    //do something
}
else if(x == 7) {
    //do something else
}
else if(x == 9) {
    //do something else
}
else {
    //do something else
}

我的问题是,编译器是否以这种方式看到if语句,或者它最终会被解释为:

if(x == 5) {
    //do something
}
else {
    if(x == 7) {
        //do something
    }
    else {
        if(x == 9) {
            //do something
        }
        else {
            //do something else
        }
    }
}

我意识到,虽然这个问题在我的脑海里是有道理的,但对其他普通民众来说,它可能听起来相当愚蠢。我更多的是指AST的外观,以及'else-if'语句是否有任何特殊的AST情况,或者它是否会被编译为级联的if/else块。

vqlkdk9b

vqlkdk9b1#

它们相当于C编译器。在C中没有特殊的语法else if。第二个if只是另一个if语句。
为了更清楚,根据C99标准,if语句定义为

selection-statement:
    if (expression) statement
    if (expression) statement else statement
    switch (expression) statement

并且复合语句被定义为

compound-statement:
    {block-item-list(opt) }
block-item-list:
    block-item
    block-item-list block-item
block-item:
    declaration
    statement

当编译器前端试图理解源代码文件时,它通常遵循以下步骤:
1.词法分析:将纯文本源代码转换为“令牌”列表
1.语义分析:解析令牌列表并生成抽象语法树(AST)
然后将树传递给编译器中端(进行优化)或后端(生成机器码)
在您的情况下,此if语句

if(x == 7) {
    //do something else
} else if(x == 9) {
    //do something else
} else {
    //do something else
}

被解析为selection-statement中的selection-statement

selection-stmt
    /     |      \
 exp     stmt     stmt
  |       |        |
 ...     ...    selection-stmt
                /      |      \
              exp     stmt    stmt
               |       |       |
              ...     ...     ...

还有这个

if(x == 7) {
    //do something else
} else {
    if(x == 9) {
        //do something else
    } else {
        //do something else
    }
}

在selection-statement内的复合语句中是相同的selection-statement:

selection-stmt
    /     |      \
 exp     stmt     stmt
  |       |        |
 ...     ...    compound-stmt
                      |
                block-item-list
                      |
                  block-item
                      |
                     stmt
                      |
                selection-stmt
                /      |      \
               exp    stmt    stmt
                |      |       |
               ...    ...     ...

他们有不同的AST。但这对编译器后端没有影响:正如你在AST中看到的,没有结构变化。

vx6bjr1n

vx6bjr1n2#

在C和C++中,将一个语句包含在一个冗余的{}对中不会改变程序的语义。这份声明

a = b;

和这个是一样的

{ a = b; }

和这个是一样的

{{ a = b; }}

还有这个

{{{{{ a = b; }}}}}

冗余的{}对编译器没有任何影响。
在您的示例中,第一个版本和第二个版本之间的唯一区别是您添加到后者的一堆冗余{},就像我在上面的a = b示例中所做的那样。您的冗余{}绝对不会改变任何东西。您所提供的两个版本的代码之间没有明显的差异,这使得您的问题基本上没有意义。
如果你想问别的问题,要么澄清你的问题,要么纠正代码。

e4yzc0pl

e4yzc0pl3#

这两段代码实际上是相同的。你可以看到为什么这是真的,通过实现“if”语句的语法如下:

if <expression>
    <block>
else
    <block>

NOTE that <block> may be surrounded by curly braces if necessary.

因此,您的代码分解如下。

// 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

现在,如果你在“else”的块周围加上花括号,这是语言允许的,你将得到你的第二种形式。

// 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

如果你对所有的“if else”子句重复这样做,你最终会得到你的第二种形式。这两段代码是完全相同的,并且编译器以完全相同的方式查看。

du7egjpx

du7egjpx4#

请注意,虽然你的第一个语句是根据if-else“阶梯”约定缩进的,但实际上它的“正确”缩进显示了真正的嵌套:

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
    }

缩进是空白;它对编译器没有任何意义。在第一个else之后是一个大的if语句。因为它只是一个语句,所以不需要用大括号括起来。当你问“编译器是那样读的吗”时,你必须记住大多数空间是微不足道的;语法确定语法树的真实嵌套。

bd1hkmkf

bd1hkmkf5#

更接近第一个,但问题并不完全符合。
当一个程序被编译时,它会经历几个阶段。第一阶段是词法分析,第二阶段是句法分析。词法分析分析文本,将其分为标记。然后语法分析查看程序的 * 结构 *,并构造抽象语法树(AST)。这是在编译过程中创建的底层语法结构。
因此,基本上,if和if-else以及if-elseif-else语句最终都被编译器构造成抽象语法树(AST)。
以下是关于AST的维基百科页面:https://en.wikipedia.org/wiki/Abstract_syntax_tree
edit:实际上,if/if else语句可能会形成更接近AST中的第二个语句。我不太确定,但如果它在底层表示为二叉树式的条件分支结构,我也不会感到惊讶。如果您有兴趣更深入地了解它,您可以对编译器理论的解析方面进行一些研究。

相关问题