类c编译器如何解释if语句
how does a C-like compiler interpret the if statement
在类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看起来如何,以及是否有任何特殊的AST案例用于'else-if'语句,或者它是否会被编译为级联if/else块。
它们相当于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
当编译器前端试图理解源代码文件时,它通常遵循以下步骤:
- 词法分析:将纯文本源代码转换为'令牌'列表
- 语义分析:解析token列表并生成抽象语法树(AST)
然后将树传递给编译器中端(优化)或后端(生成机器代码)
在你的例子中,if语句
if(x == 7) {
//do something else
} else if(x == 9) {
//do something else
} else {
//do something else
}
被解析为一个选择语句中的一个选择语句,
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-stmt
/ |
exp stmt stmt
| | |
... ... compound-stmt
|
block-item-list
|
block-item
|
stmt
|
selection-stmt
/ |
exp stmt stmt
| | |
... ... ...
所以它们有不同的ast。但这对编译器后端没有影响:正如您在AST中看到的,没有结构上的变化。
在C和c++中,将语句封装到冗余的{}
对中不会改变程序的语义。这句话
a = b;
等于这个
{ a = b; }
等于这个
{{ a = b; }}
和这个
{{{{{ a = b; }}}}}
多余的{}
对编译器来说绝对没有区别。
在您的示例中,第一个版本和第二个版本之间的唯一区别是您添加到后者的一堆冗余{}
,就像我在上面的a = b
示例中所做的那样。您的冗余{}
绝对不会改变任何东西。你给出的两个版本的代码之间没有明显的区别,这使得你的问题本质上没有意义。
如果你想问别的问题,要么澄清你的问题,要么纠正代码。
这两段代码实际上是相同的。通过了解"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"重复执行此操作从句,你最终会得到第二种形式。这两段代码完全相同,并且被编译器以完全相同的方式看待。
请注意,尽管您的第一个语句是根据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
语句。因为它只是一个语句,所以不需要用大括号括起来。当你问"编译器是这样读的吗"时,你必须记住,大多数空间都是无关紧要的;语法决定语法树的真正嵌套。
更接近第一个,但是这个问题不完全适合。
当一个程序被编译时,它要经历几个阶段。第一阶段是词法分析,第二阶段是句法分析。词法分析分析文本,把它分成不同的符号。然后语法分析查看程序的结构,并构造抽象语法树(AST)。这是在编译过程中创建的底层语法结构。
基本上,if和if-else以及if-elseif-else语句最终都被编译器构造成一个抽象语法树(AST)。
这是ast的维基百科页面:https://en.wikipedia.org/wiki/Abstract_syntax_tree
编辑:实际上,if/if else语句可能在AST中形成了更接近于第二个语句的东西,我不太确定,但如果它在底层被表示为二叉树状的条件分支结构,我不会感到惊讶。如果您有兴趣更深入地了解它,可以对编译器理论的解析方面进行一些研究。
- 请解释"函数1(p1,p2,p3);"的输出
- 请解释这句话(cout<<1+int((a<b)^((b-a)&1) )<<endl
- 我的简单if-else语句是如何无法访问的代码
- 如何将enable-if与模板参数和参数包一起使用
- 无论条件是否为true,if总是在c++中执行
- Arduino:for/while/if在void setup()或void loop()之前?——错误:之前需要不合格
- 被解释为低级别const的const对象的地址
- Insert函数不适用于2 if语句C++
- 计算每个节点的树高,帮助我解释这个代码解决方案
- MSVC将仅移动结构参数解释为指针
- If语句未被求值C++
- C++嵌套if语句,基本货币交换
- 多个If语句与使用逻辑运算符计算条件的单个语句的比较
- 是否可以使用if constexpr删除控制流语句
- 有人可以解释一下吗?这是关于数组和数组内部 if 语句的一些处理
- 如何解释 #if/#else 位域?(VC++菜鸟)
- 这个 FOR-IF 循环的解释是什么?
- C ++ if else 语句在开关大小写 - 解释
- 类c编译器如何解释if语句
- 解释C++中的#define PRINTF if(false)PRINTF