First to say, the error you post is a syntax error related to the format of a case
label statement. It allows you to use only an executable statement, and not a declaration. Put an empty statement before the declaration and you'll be ok. Try the following:
#include <stdio.h>
int main()
{
switch(3) {
int x = 3; /* the initializer is ignored by the compiler
* you can include declarations here, but as
* this code is never executed, the initializer
* never takes place. */
case 3:; /* <=== look this semicolon to allow the next declaration */
int y = 5;
printf("x = %d, y = %d\n", x, y);
break;
}
}
The first variable, x
, will be declared properly, but the initializer will not be executed, as the case statement selected is the one corresponding to case label 3
. The printf
will print
x = 0, y = 5
(note: this happens on my machine, as the variable x
is not initialized, Undefined Behaviour is expected)
In C, some evolution has been realized over the years, concerning the use of declarations in a block.
In ancient C, variables can be declared only at the beginning of a block (the piece of code between {
and }
, but this approach has been thrown for the new possibility of declaring a variable whenever you need it (even after some executable sentences after a block begin) But a case
statement permits only to put an executable statement, and not a declaration, so that's the reason of your compiler error.
If you follow the ancient C way, you can only declare new local variables only after the opening {
curly brace after the switch, as in:
switch(something) {
int var1;
case BLA_BLA:
/* use var1 here */
which, although counterintuitive, is valid since the old K&R code. The problem with this approach is that the variable is valid from the point of definition until the end of the switch statement, and so, it is global to all the case parts.
Another way, is the form you propose, in which you declare a new block by opening curly braces. This works also since the old K&R code, and makes it easier to control the scope of the variables defined. Personally, I prefer this second approach. A block is an executable statement, so there's no problem in using it as the labeled case statement of the switch (the declarations happen inside it).
Case labels don't delimit blocks of code, they label executable statements, so their syntax is specific to the case
statement syntax (which finishes after the semicolon of the statement it is attached to, or the closing curly br)