代码之家  ›  专栏  ›  技术社区  ›  TruthSeeker

在C中循环切换案例

  •  4
  • TruthSeeker  · 技术社区  · 8 年前

    我最近遇到了下面显示的代码片段,我本来以为它是语法错误,但令我惊讶的是,代码产生了有效的输出。

    #include <stdio.h>
    
    int main(void) {
        int x = 2;
    
        switch(x) {
        case 1: printf("1"); break;
    
            do {
                case 2: printf("2 "); break;
                case 3: printf("3 "); break;
            } while(++x < 4);
    
            case 4: printf("4"); break;
        }
        return 0;
    }
    

    output: 2 4
    

    编译程序: 海湾合作委员会6.3

    我发现了一个类似的问题,但不能完全证明上述情况的合理性, Mixed 'switch' and 'while' in C

    有人能解释一下吗?

    1. 这里到底发生了什么?
    2. 为什么不是语法错误?
    3. 为什么跳过案例“3”?
    2 回复  |  直到 8 年前
        1
  •  5
  •   Petr Skocik    8 年前

    case X: some_statement; 是一个 labeled statement (6.8.1) 就像 goto_label: some_statement; 唯一需要注意的是 case / default 标签只能出现在 switch (可能在任意嵌套的复合语句中)。这使得 案例 语句只是非常松散地与 转换 在句法上。

    语义上, 转换 ES可通过计算实现 goto 像普通的一样 古托 S,它们几乎可以在任何地方跳跃(在C11中,你不能跳过 VLA 声明)包括循环内部(请参见 https://en.wikipedia.org/wiki/Duff%27s_device#Mechanism 另一个描述)。

    在你的例子中, case 3: 被跳过,因为 break 但是 case 4: 是因为 打破 之后 案例3: 是循环中断 打破 ,不是开关断开 打破 ( 打破 / continue 始终应用于它们可以应用的最近构造)。

        2
  •  0
  •   Eric Postpischil    8 年前

    A的官方C语法 switch 声明如下:

    转换 ( 表达 ) 陈述

    任何 陈述 可以是 带标签的语句 ,其中语法包括:

    案例 常量表达式 : 陈述

    这意味着你可以把你想要的任何东西放在 转换 :它可以是包含多个语句和 do - while 包含多个语句的语句,以及 case 可以在这些语句的前面加上标签。

    编译器只使用跳转指令(在它的抽象机器中)来实现切换;在优化之后,它们可能会作为其他指令结束。循环语句,例如 - 虽然 使用测试控制表达式和有条件跳转的代码实现。因此,尽管您在结构化语言中考虑到了很好的结构,但它归结为跳转指令,并且可以根据需要将这些指令交织在一起。

    跳跃并不是其中最令人不安的部分。对象初始化和生存期更值得关注。如果不小心,switch语句可能会无意中跳过对象的初始化。

    这个 printf 因为控件从 转换 case 2 ,然后中断,退出 - 虽然 . 这将在 case 4 语句,打印4,然后从 转换 语句。