回顾一些第三方C代码,我遇到了类似的内容:
switch (state) {
case 0:
if (c=='A') { // open brace
// code...
break; // brace not closed!
case 1:
// code...
break;
} // close brace!
case 2:
// code...
break;
}
在我正在审查的代码中,这似乎只是一个错字,但我很惊讶它编译时没有错误。
为什么这是有效的C?
与在预期位置关闭支撑相比,对此代码执行的影响是什么?
有什么情况可以使用吗?
编辑:在示例中,我查看了所有中断(如上所述) - 但如果在0或1的情况下中断,则答案也可能包括行为。
答案 0 :(得分:12)
它不仅有效,在实际代码中使用了类似的结构,例如Duff's Device,这是一个用于复制缓冲区的展开循环:
send(to, from, count)
register short *to, *from;
register count;
{
register n = (count + 7) / 8;
switch(count % 8) {
case 0: do { *to = *from++;
case 7: *to = *from++;
case 6: *to = *from++;
case 5: *to = *from++;
case 4: *to = *from++;
case 3: *to = *from++;
case 2: *to = *from++;
case 1: *to = *from++;
} while(--n > 0);
}
}
由于switch
语句实际上只是计算地址并跳转到它,因此很容易理解为什么它可以与其他控制结构重叠;其他控制结构中的行也有跳转目标的地址!
在您提交的案例中,假设您的代码中没有switch
或break
。当您完成执行then
语句的if
部分后,您就继续前进,这样您就可以进入case 2:
。现在,由于您拥有switch
和break
,因此break
可以突破的重要性。根据{{3}},
中断语句终止执行最近的封闭执行,执行,切换或 while 语句出现。控制传递给终止语句后面的语句。
由于最近的执行, ,切换,而语句是您的切换(请注意如果未包含在该列表中),那么如果您在then
块内,则转移到switch
语句的外部。但是,如果您输入case 0
但c == 'A'
为假,会发生什么更有趣的事情。然后if
将控件转移到then
块的右括号之后,然后开始执行case 2
中的代码。
答案 1 :(得分:3)
在C和C ++中,只要不跳过任何变量声明,就跳入循环和if块是合法的。您可以使用goto
检查this answer示例,但我不明白为什么相同的想法不适用于switch
块。
语义与}
高于case 1
时的语义不同。
这段代码实际上是说state == 0
和c != 'A'
然后转到case 2
,因为那是if
语句的右括号。然后它处理该代码并点击break
代码末尾的case 2
语句。