在switch语句中第一个'case'之前的代码

时间:2010-01-20 12:49:38

标签: c switch-statement

在C中,可以在第一个case标签之前编写代码。有没有这样做的情况,或者它只是一个“死代码块”?

E.g:

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

4 个答案:

答案 0 :(得分:18)

我认为这不是一个特征,而是C对待switch / case的工件 - 只是一系列跳转目标而不受语法限制。这就是为什么Duff's device有效,这也是为什么第一个case之前的代码无法运行的原因。

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

    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

答案 1 :(得分:12)

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

所以尽管这是允许的,但很容易就是其中之一“仅仅因为你不能意味着你应该”的情况。该构造令人困惑,并且很容易导致使用未初始化的变量,因为很难确定是否以及初始化发生的位置。

答案 2 :(得分:11)

声明范围仅限于switch块的变量可能很有用(但请注意,将跳过这些变量的任何初始化器):

switch (...)
{
    int n;

    case 0:
    ...
}

理论上,您也可以使用goto将代码放在那里。

答案 3 :(得分:1)

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

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

这与你想要的不一样吗? (除非在您的示例中,如果编译器没有抱怨,代码将永远不会运行。)