“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 if
。 g++ -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
它本身不形成有意义的语句,那么解析器继续。