Join the Stack Overflow Community
Stack Overflow is a community of 6.6 million programmers, just like you, helping each other.
Join them; it only takes a minute:
Sign up

Through a little typo, I accidentally found this construct:

int main(void) {
    char foo = 'c';

    switch(foo)
    {
        printf("Cant Touch This\n");   // This line is Unreachable

        case 'a': printf("A\n"); break;
        case 'b': printf("B\n"); break;
        case 'c': printf("C\n"); break;
        case 'd': printf("D\n"); break;
    }

    return 0;
}

It seems that the printf at the top of the switch statement is valid, but also completely unreachable.

I got a clean compile, without even a warning about unreachable code, but this seems pointless.

Should a compiler flag this as unreachable code?
Does this serve any purpose at all?

share|improve this question
12  
GCC has a special flag for this. It's -Wswitch-unreachable – Eli Sadoff 17 hours ago
11  
"Does this serve any purpose at all?" Well, you can goto in and out of the otherwise unreachable part, which may be useful for various hacks. – HolyBlackCat 17 hours ago
6  
@HolyBlackCat Wouldn't that be such for all unreachable code? – Eli Sadoff 17 hours ago
10  
@EliSadoff Indeed. I guess it doesn't serve any special purpose. I bet it is allowed just because there is no reason to forbid it. After all, switch is just a conditional goto with multiple labels. There are more or less same restrictions on it's body as you would have on a regular block of code filled with goto labels. – HolyBlackCat 17 hours ago
4  
@HolyBlackCat The body doesn't even have to be a block. Any statement will do. – PSkocik 17 hours ago

Perhaps not the most useful, but not completely worthless. You may use it to declare a local variable available within switch scope.

switch (foo)
{
    int i;
case 0:
    i = 0;
    //....
case 1:
    i = 1;
    //....
}

The standard has the following sample:

EXAMPLE    In the artificial program fragment

switch (expr)
{
    int i = 4;
    f(i);
case 0:
    i = 17;
    /* falls through into default code */
default:
    printf("%d\n", i);
}

the object whose identifier is i exists with automatic storage duration (within the block) but is never initialized, and thus if the controlling expression has a nonzero value, the call to the printf function will access an indeterminate value. Similarly, the call to the function f cannot be reached.

P.S. BTW, the sample is not valid C++ code. Clang complains about jump to default: (and to case 1:):

error: cannot jump from switch statement to this case label
default:
note: jump bypasses variable initialization
int i = 4;

However just defining i without initialization compiles.

share|improve this answer
    
"... but is never initialized ..." Looks like i is initialized to 4, what am I missing? – yano 17 hours ago
4  
Note that if the variable is static, it will be initialized to zero, so there's a safe usage for this as well. – Leushenko 17 hours ago
11  
@yano We always jump over the i = 4;initialization, so it never takes place. – AlexD 17 hours ago
6  
Hah of course! ... whole point of the question ... geez. The desire is strong to delete this stupidity – yano 17 hours ago

Does this serve any purpose at all?

Yes. If instead of a statement, you put a declaration before the first label, this can make perfect sense:

switch (a) {
  int i;
case 0:
  i = f(); g(); h(i);
  break;
case 1:
  i = g(); f(); h(i);
  break;
}

The rules for declarations and statements are shared for blocks in general, so it's the same rule that allows that that also allows statements there.


Worth mentioning as well is also that if the first statement is a loop construct, case labels may appear in the loop body:

switch (i) {
  for (;;) {
    f();
  case 1:
    g();
  case 2:
    if (h()) break;
  }
}

Please don't write code like this if there is a more readable way of writing it, but it's perfectly valid, and the f() call is reachable.

share|improve this answer
1  
shoot, yeah, I've seen that loop construct before, but totally forgot about it. Scaaary. – Marcus Müller 17 hours ago

Assuming you are using gcc on linux, it would have given you warning if you're using 4.4 or earlier version.

-Wunreachable-code option was removed in gcc 4.4 onward. https://gcc.gnu.org/ml/gcc-help/2011-05/msg00360.html

share|improve this answer
1  
When you know why, you know why. Interesting. Thanks. – Jonathan Leffler 17 hours ago
    
Having experienced the issue first hand always helps! – 16tons 17 hours ago

You got your answer related to the required gcc option -Wswitch-unreachable to generate the warning, this answer is to elaborate on the usability / worthyness part.

Quoting straight out of C11, chapter §6.8.4.2, (emphasis mine)

switch (expr)
{
int i = 4;
f(i);
case 0:
i = 17;
/* falls through into default code */
default:
printf("%d\n", i);
}

the object whose identifier is i exists with automatic storage duration (within the block) but is never initialized, and thus if the controlling expression has a nonzero value, the call to the printf function will access an indeterminate value. Similarly, the call to the function f cannot be reached.

Which is very self-explanatory. You can use this to define a locally scoped variable which is available only within the switch statement scope.

share|improve this answer

Not only for variable declaration but advanced jumping as well. You can utilize it well if and only if you're not prone to spaghetti code.

int main()
{
    int i = 1;
    switch(i)
    {
        nocase:
        printf("no case\n");

        case 0: printf("0\n"); break;
        case 1: printf("1\n"); goto nocase;
    }
    return 0;
}

Prints

1
no case
0 /* Notice how "0" prints even though i = 1 */

It should be noted that switch-case is one of the fastest control flow clauses. So it must be very flexible to the programmer, which sometimes involves cases like this.

share|improve this answer

It should be noted, that there are no structural restrictions on the code within the switch statement, or on where the case *: labels are placed within this code. This makes programming tricks like duff's devise possible, one possible implementation of which looks like this:

int n = ...;
int iterations = n/8;
switch(n%8) {
    while(iterations--) {
        sum += *ptr++;
        case 7: sum += *ptr++;
        case 6: sum += *ptr++;
        case 5: sum += *ptr++;
        case 4: sum += *ptr++;
        case 3: sum += *ptr++;
        case 2: sum += *ptr++;
        case 1: sum += *ptr++;
        case 0:
    }
}

You see, the code between the switch(n%8) { and the case 7: label is definitely reachable...

share|improve this answer

It is possible to implement a "loop and a half" with it, although it might not be the best way to do it:

char password[100];
switch(0) do
{
  printf("Invalid password, try again.\n");
default:
  read_password(password, sizeof(password));
} while (!is_valid_password(password));
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.