在C中,可以在第一个case
标签之前编写代码。有没有这样做的情况,或者它只是一个“死代码块”?
E.g:
switch (...) {
{
int a = 0x2a;
printf("%d\n", a);
}
case 0:
...
}
答案 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:
...
}
这与你想要的不一样吗? (除非在您的示例中,如果编译器没有抱怨,代码将永远不会运行。)