First some background on how switch
(really) works:
A switch
is usually thought of as a construct that selects a piece of code to execute depending on the value of some expression, as in
switch (x) {
case 1:
foo();
break;
case 2:
bar();
break;
}
However, it's more accurate to think of a switch
as a form of computed goto
statement. For example, the following is perfectly legal:
switch (x) {
puts("I can't be reached");
case 1:
if (cond) {
case 2:
puts("Either x == 1 && cond, or x == 2");
}
}
Depending on the value of x
, the program will jump to either case 1
or case 2
(or past the switch
if x
is neither 1 nor 2).
Your program will compile as C (with junk values for x
and y
inside the switch
, since the initializations are skipped), but not as C++. The reason is that C++ does not allow a jump to a case
label to cross the initialization of a variable. For simple types like int
, skipping over int x;
is allowed (since no initialization is involved), but not skipping over int x = 1;
.
The main motivation for this difference is probably that letting a jump to a case
label cross an initialization in C++ would be unsafe when constructors are involved. For example, if C++ allowed a case
label to occur after a definition My_class my_object
within some scope, then jumping to that case
label would skip my_object
's constructor but still run its destructor when exiting the scope.
The same restrictions apply to goto
in C++. You can't use it to jump into a block and past a variable initialization.
As a side note, switch
follows the same general syntax as if
and while
. The syntax of if
as given in the C11 standard (ISO/IEC 9899:2011, section 6.8.4) is
if ( expression ) statement
, while the syntax of switch
is
switch ( expression ) statement
The only difference as far as statement is concerned (in C -- C++ adds some more limitations as mentioned above) is that it is allowed to contain case
labels (and break
) for a switch
but not for an if
(unless the if
occurs within a switch
).
Just as with an if
, you can even leave off the braces and write code like the following. (Whether this is unnecessarily confusing is another discussion.)
switch (x) case 1: case 2: puts("x is 1 or 2");
Syntactically, case
and default
labels belong in the same category as goto
labels. Section 6.8.1 of the C11 standard has the following definition:
labeled-statement:
identifier : statement
case constant-expression : statement
default : statement