切换案例奇怪的范围

回顾一些第三方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的情况下中断,则答案还可以包括行为。

它不仅有效,在实际代码中也使用了类似的结构,例如Duff的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语句实际上只是计算一个地址并跳转到它,因此很容易看出为什么它可以与其他控制结构重叠; 其他控制结构中的行也有跳转目标的地址!

在您提供的情况下,想象您的代码中是否没有switchbreak 。 当你完成执行if语句的then一部分时,你就继续前进,所以你会陷入case 2: . 现在,既然你有switchbreak ,重要的是break可以突破。 根据MSDN页面,“The C break statement” ,

break语句终止执行它出现的最近的封闭doforswitchwhile语句。 控制传递给终止语句后面的语句。

由于最近的封闭doforswitchwhile语句是您的开关 (请注意, 如果未包含在该列表中),那么如果您在then块内, then转移到switch语句的外部。 但是,更有趣的是,如果输入case 0会发生什么,但是c == 'A'是假的。 然后, if将控制转移到then块的右括号then ,并开始执行case 2的代码。

在C和C ++中,只要不跳过任何变量声明,就跳入循环和if块是合法的。 您可以使用goto查看此答案以获取示例,但我不明白为什么相同的想法不适用于switch块。

语义不同于如果}高于case 1正如您所期望的那样。
这段代码实际上说如果state == 0c != 'A'那么转到case 2因为那是if语句的右括号。 然后它处理该代码并在case 2代码的末尾命中break语句。