tags:

views:

252

answers:

4

In C it's possible to write code before the first case label. Are there any cases for which it is useful to do this or is it just a 'dead block of code' ?

E.g.:

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

I think this is less a feature than an artifact of how C treats switch/case—as just a series of jump targets without restrictions on the syntax. That's why Duff's device works and that's also why the code before the first case won't ever run.

If you look at the generated assembly you'll see that the code will just be jumped over:

    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
Joey
A: 

I don't understand what your after. Why not just put the code before the case?

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

Isn't that the same as what you intend ? (apart from in your example the code would never run if the compiler doesn't complain.)

Tony Lambert
The printf in my example was chosen randomly.
tur1ng
does it matter? questions should be asked of everything
Matt Joiner
+6  A: 

It can be useful to declare variables that have a scope limited to the switch block (but be aware that any initialisers for those variables will be skipped):

switch (...)
{
    int n;

    case 0:
    ...
}

In theory, you could also put code there that you get to using goto.

caf
If you want a variable in this scope, start a block just before the switch and declare the variable in there, i.e. enclose the whole switch statement in another set of brackets. Declaring it inside switch but not in a case doesn't work.
Martin
@Martin: Variable declarations *do* work as they don't produce any output code; they're merely there for the compiler to note “Ah, I know this variable, I've seen it back there”.
Joey
"any initialisers for those variables may be skipped" - is it even that simple (the initializer is either skipped or isn't), or is it undefined behaviour/ill-formed program to jump over an initializer? I can't remember.
Steve Jessop
+5  A: 

The C standard document has an example that explains exactly the behavior of this type of construct (6.8.4.2/7 "The switch statement"):

EXAMPLE In the artificial program fragment

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

the object whose identifier is i exists with automatic storage duration (within the block) but is never initialized, and thus if the controlling expression has a nonzero value, the call to the printf function will access an indeterminate value. Similarly, the call to the function f cannot be reached.

So even though this is permitted, it's easily one of those "just because you can doesn't mean you should" situations. The construct is confusing and can easily lead to using an uninitialized variable since it can be very unclear whether and where the initialization occurs.

Michael Burr
C standard document can be found at: http://www.open-std.org/JTC1/SC22/wg14/www/docs/n1336.pdf
tur1ng