第一个';案例';在switch语句中

第一个';案例';在switch语句中,c,switch-statement,C,Switch Statement,在C语言中,可以在第一个case标签之前编写代码。在某些情况下,这样做有用吗?还是仅仅是“死代码块” 例如: 我认为这与其说是一个特性,不如说是C如何将开关/大小写-视为一系列不受语法限制的跳转目标的产物。这就是为什么工作的原因,也是为什么第一个案例之前的代码永远不会运行的原因 如果查看生成的程序集,您将看到代码将被跳过: mov ecx, DWORD PTR _x$[ebp] mov DWORD PTR tv64[ebp], ecx cmp DWORD PTR tv64

在C语言中,可以在第一个
case
标签之前编写代码。在某些情况下,这样做有用吗?还是仅仅是“死代码块”

例如:


我认为这与其说是一个特性,不如说是C如何将
开关
/
大小写
-视为一系列不受语法限制的跳转目标的产物。这就是为什么工作的原因,也是为什么第一个
案例之前的代码永远不会运行的原因

如果查看生成的程序集,您将看到代码将被跳过:

    mov ecx, DWORD PTR _x$[ebp]
    mov DWORD PTR tv64[ebp], ecx
    cmp DWORD PTR tv64[ebp], 0                  ; here begins the switch
    je  SHORT $LN1@main                         ; jump to case 0
    jmp SHORT $LN4@main                         ; jump out of the switch
; Line 8
    mov DWORD PTR _a$752[ebp], 42
; Line 9
    mov edx, DWORD PTR _a$752[ebp]              ; here we have the dead code
    push    edx
    push    OFFSET $SG754
    call    _printf
    add esp, 8
$LN1@main:                                      ; and here case 0
; Line 12
    push    OFFSET $SG756
    call    _printf
    add esp, 4
$LN4@main:
; Line 15
    xor eax, eax
    mov esp, ebp
    pop ebp
    ret 0

我不明白你在追求什么。为什么不把代码放在案例之前

int a = 0x2a;
printf("%d\n", a);
switch (...)    {
case 0:
...
}

这和你的意图不一样吗?(除了在您的示例中,如果编译器不抱怨,代码将永远不会运行。)

声明范围限制在
开关
块的变量可能会很有用(但请注意,这些变量的任何初始值设定项都将被跳过):


理论上,您也可以使用
goto

将代码放在那里。C标准文档中有一个示例,精确地解释了这种类型构造的行为(6.8.4.2/7“switch语句”):

艺术节目片段中的示例

switch (expr)
{
    int i = 4;
    f(i);
case 0:
    i  =  17;
    /*  falls through into default code  */
default:
    printf("%d\n", i);
}
标识符为
i
的对象以自动存储持续时间(在块内)存在,但从未初始化,因此如果控制表达式具有非零值,则对
printf
函数的调用将访问不确定值。同样,无法调用函数
f


所以,即使这是允许的,它也很容易成为一种“仅仅因为你可以,并不意味着你应该”的情况。该构造令人困惑,很容易导致使用未初始化的变量,因为初始化是否发生以及在何处发生可能非常不清楚。

试试看?????我尝试了许多不同的示例,上面的示例只是为了澄清。但总有一种可能,我错过了(GNU)C的一个特性,在这个区域可以做一些事情。我示例中的printf是随机选择的。这有关系吗?所有的问题都应该被问到如果你想在这个范围内有一个变量,在开关前启动一个块,并在那里声明变量,也就是说,把整个开关语句放在另一组括号中。在switch内部声明它,但不在case中声明它是不起作用的。@Martin:变量声明起作用,因为它们不产生任何输出代码;它们只是为了让编译器注意到“啊,我知道这个变量,我在那里看到过它”。“这些变量的任何初始值设定项都可能被跳过”-它是否那么简单(初始值设定项被跳过或没有),或者跳过初始值设定项是未定义的行为/格式错误的程序?我不记得了。你真的建议使用
goto
?我认为这是非常糟糕的做法。@Arc676这是一个常见的误解,即使在有经验的程序员中也是如此。它始于Dijkstra的一篇好论文,但正如Steele在“揭穿‘昂贵的过程调用’神话”中指出的那样,goto本身并不坏,但滥用goto却很糟糕。斯蒂尔:“我们试图通过禁止构造来消除不必要的概念和编程风格。”Goto可以很好地使用,但最好是少用。正如他还指出的,如果充分滥用,可以使用其他控制结构来编写模糊代码。底线是避免混淆代码(使用goto轻松编写),而不仅仅是goto本身。C标准文档可在以下网址找到:
switch (...)
{
    int n;

    case 0:
    ...
}
switch (expr)
{
    int i = 4;
    f(i);
case 0:
    i  =  17;
    /*  falls through into default code  */
default:
    printf("%d\n", i);
}