Why can't variables be declared in a switch statement?
Solution 1:
Case
statements are only labels. This means the compiler will interpret this as a jump directly to the label. In C++, the problem here is one of scope. Your curly brackets define the scope as everything inside the switch
statement. This means that you are left with a scope where a jump will be performed further into the code skipping the initialization.
The correct way to handle this is to define a scope specific to that case
statement and define your variable within it:
switch (val)
{
case VAL:
{
// This will work
int newVal = 42;
break;
}
case ANOTHER_VAL:
...
break;
}
Solution 2:
This question is was originally tagged as [C] and [C++] at the same time. The original code is indeed invalid in both C and C++, but for completely different unrelated reasons.
In C++ this code is invalid because the
case ANOTHER_VAL:
label jumps into the scope of variablenewVal
bypassing its initialization. Jumps that bypass initialization of automatic objects are illegal in C++. This side of the issue is correctly addressed by most answers.-
However, in C language bypassing variable initialization is not an error. Jumping into the scope of a variable over its initialization is legal in C. It simply means that the variable is left uninitialized. The original code does not compile in C for a completely different reason. Label
case VAL:
in the original code is attached to the declaration of variablenewVal
. In C language declarations are not statements. They cannot be labeled. And this is what causes the error when this code is interpreted as C code.switch (val) { case VAL: /* <- C error is here */ int newVal = 42; break; case ANOTHER_VAL: /* <- C++ error is here */ ... break; }
Adding an extra {}
block fixes both C++ and C problems, even though these problems happen to be very different. On the C++ side it restricts the scope of newVal
, making sure that case ANOTHER_VAL:
no longer jumps into that scope, which eliminates the C++ issue. On the C side that extra {}
introduces a compound statement, thus making the case VAL:
label to apply to a statement, which eliminates the C issue.
-
In C case the problem can be easily solved without the
{}
. Just add an empty statement after thecase VAL:
label and the code will become validswitch (val) { case VAL:; /* Now it works in C! */ int newVal = 42; break; case ANOTHER_VAL: ... break; }
Note that even though it is now valid from C point of view, it remains invalid from C++ point of view.
-
Symmetrically, in C++ case the the problem can be easily solved without the
{}
. Just remove the initializer from variable declaration and the code will become validswitch (val) { case VAL: int newVal; newVal = 42; break; case ANOTHER_VAL: /* Now it works in C++! */ ... break; }
Note that even though it is now valid from C++ point of view, it remains invalid from C point of view.