Question:
Hello. While trying to answer one of the questions here, I was surprised to find that the following code
#include <stdio.h>
int main()
{
int a = 123;
const char *r = "initial value";
switch (a) {
case 1: r = "1"; break;
if (0) {
default: r = "not 1";
}
}
puts(r);
return 0;
}
GCC compiles normally and prints at runtime
not 1
It seems to me that the code is clearly with such an error that it should not even compile. What's the matter here?
Answer:
The body of a switch
(like the body of while
, do/while
, for
, etc.) is just a statement in which we place the case
and default
labels, and in which the use of break
possible. No more.
The case
and default
labels can appear only inside a statement belonging to some switch
, but otherwise the restrictions imposed on the arrangement of these labels are no different from any other labels.
In a similar way, the transfer of control to these labels occurs according to rules similar to goto
rules, with the only difference that only the immediately enclosing switch
can transfer control to the case
and default
label.
In your case, if you replace the case
and default
labels with "regular" labels, we get just a compound statement
{
l1:
r = "1"; break;
if (0) {
l2:
r = "not 1";
}
}
There is nothing unusual in this compound statement. The position of the labels in it does not violate any language rules. It is not unusual for the default:
label to transfer control to a branch of some if
.
Nobody forces you to even use the compound statement to implement the switch
body, i.e. contrary to common practice, the switch
body does not need to be enclosed in {}
. You can use any other type of statament and place labels in it
int i = rand() % 4;
switch (i)
if (0) case 0: printf("Privet!\n");
else if (0) case 1: printf("Hello!\n");
else if (0) case 2: printf("World!\n");
else default: printf("Ku-ku!\n");
Note that this great switch
technique saves you the trouble of remembering break
at the end of each branch.