“if”没有花括号的块会使后续的“else if”嵌套

AFAIK,如果没有提供“if”块,那么花括号内部只会考虑1个语句。 例如

if(..) statement_1; statement_2; 

无论选项卡如何, if块中都只考虑statement_1

以下代码与此不相符:

 int main () { if(false) // outer - if if(false) // nested - if cout << "false false\n"; else if(true) cout << "true\n"; } 

上面的代码不打印任何东西。 它应该打印"true"
else if自动嵌套在外部 if块中,它将显示为else ifg++ -Wall发出警告,但这不是问题。 一旦你把花括号,一切都按预期的顺利。

为何如此不同的行为?
[海湾合作委员会演示: 没有牙箍和大括号 ]。

行为实际上并没有不同,它完全一致:整个内部if块 – 包括else if – 被认为是一个块。

这是解析中的经典歧义,称为“悬空 – else问题” :当在普通BNF中写下语法时,有两种有效的解析方法:

尾随的else是外部块的一部分,或者是内部块的一部分。

大多数语言通过(任意)决定解析器贪婪地匹配块来解决模糊性 – 即将else [ if ]分配给最接近的if

因为else实际上是与内部 if组合而不是外部组合。 它实际上被解析为

 int main () { if(false) // outer - if (never gets executed) { if(false) // nested - if { cout << "false false\n"; } else if(true) { cout << "true\n"; } } } 

您可以通过明确地将大括号放在您想要的位置来解决问题。

它不应该打印任何东西。 它等同于此,因为第二个if / else if是属于第一个if的一个块:

  if(false) { if(false) // nested - if cout << "false false\n"; else if(true) cout << "true\n"; } 

从C解析器viepoint很自然。

解析器在解析if语句时首先解析条件表达式,然后在条件之后解析第一个语句,然后查找else关键字,如果else出现,则解析第二个(替代)语句。

但是,第一个语句也是if语句,因此解析器递归调用“if-parser”(在测试else关键字之前!)。 此递归调用完全解析内部if-else语句(包括else ),并将标记位置“移动到整个代码片段的末尾”。

任何实现替代行为的尝试都应该涉及“外部”和“内部”if-parser之间的一些额外的通信:外部解析器应该告知“内部”不要贪婪(即不要吃掉else语句)。 这会增加语言语法的额外复杂性。

else语句总是附加到最近的if 。 没有分支嵌套, if它本身不形成有意义的语句,那么解析器继续。