I, too, don't understand what the "case 0:;" stuff is getting at.
I don't think this should work either
Code:
int number = 0;
switch (number) {
case 0:;
NSObject * object = [[NSObject alloc] init];
break;
default:
break;
}
I will probably give it a try, though, later and see what happens.
I thought that the C spec doesn't allow declaring variables where there is a mismatch between variable scope and flow control -- that is, it wants to prevent the situation where a program could jump over the declaration of a variable to a place where that variable is in scope. switch statements and gotos have this potential mismatch. while, do while and if statements do not have this potential. I'd be surprised if there was some way to trick out the compiler into allowing this after all. Live and learn, though!
It works because:
1) a label must be immediately followed by a statement; declarations are
not statements (see page 131 of the ISO spec)
2) a single ; is an acceptable statement, it just does nothing
I'm not 100% sure of the rationale behind not allowing a declaration to follow a label, but it might be something like this: A label assigns a name to the address in memory of an instruction. A declaration doesn't generate instructions in the typical manner (it tells the compiler how much stack space to allocate) so it's unclear what memory address you would associate with the label.
It doesn't have anything to do with scope. Variables can be declared anywhere else in a switch statement. For example, the following code compiles with no errors:
Code:
switch (a)
{
int b = 9;
case 0:
printf("zero; b = %d\n", b);
int c = 10;
break;
case 1:
printf("one; b = %d, c = %d\n", b, c);
int d = 11;
default:
printf("other; b = %d, c = %d, d = %d\n", b, c, d);
}
b, c, and d are all in scope; space for them has been allocated on the stack. However, b's value will be garbage because the switch statement jumps over its initializer. Likewise, if a = 1, c will be used uninitialized, and if a is neither 0 nor 1, then b, c, and d will be used uninitialized.
The only reason that something like
Code:
switch (a)
{
case 0:
int b = 9;
// ...
}
doesn't work is because a label can only precede a statement, and declarations (even with initializers) are not statements. Likewise, this doesn't work either:
Code:
void myfunction()
{
if (!do_stuff())
goto mylabel;
mylabel:
int i = 3;
do_more_stuff();
}
The best way to declare variables in a case block is just to enclose the block in curly braces. While it's a nice trick, using lone semicolons leads to confusion (especially when used to indicate for/while loops with empty bodies)