Fun with switch case, Part II

In last week’s Lesson, I reviewed the switch-case structure and how declared constants aren’t truly the kind of constant a case statement requires. This week I continue my exploration of switch-case, with an interesting and surprising quirk of the default condition.

To review, the default condition is what’s executed when none of the case statements yield a match. It’s labeled like case, and works the same:

default:

Most programmers know that the default statement is optional. After all, it’s called a switch-case structure and not switch-case-default. If you don’t need a default condition, it can be omitted. But another interesting and obscure fact is that the default statement can dwell anywhere in the switch block.

Traditionally, coders put default last. I believe it’s because the progression is how we think, but also it kind of mirrors an if-else statement, with default handling the “else” part. Even so, you don’t have to put default last, as the following code demonstrates.

2024_03_02-Lesson.c

#include <stdio.h>

int main()
{
    int a;

    printf("1, 2, 3: ");
    scanf("%d",&a);

    switch(a)
    {
        case 1:
            puts("One!");
            break;
        default:
            puts("You bad!");
            break;
        case 2:
            puts("Two!");
            break;
        case 3:
            puts("Three!");
            break;
    }

    return 0;
}

Normally, I would expect to see case 1, case 2, case 3, and then default. But above, I snuck the default part amid the case statements. I have no justification for doing so, only to prove that the code builds and runs.

In fact, it might make more sense to put default first, though my point is that it can go anywhere. A rule doesn’t exist in C programming that default must come last — if it’s used at all.

I’m unaware whether this trick works in other programming languages. Seeing how most languages have their roots in C, my guess is that it does.

Another interesting perspective on switch-case is that it offers a primitive form of recursion. This observation makes more sense than comparing switch-case to a stacked if-else if-else construction, though such a comparison is a better way to teach the topic.

Still, the processor repeatedly “calls” each case statement, evaluating them until a solution is found. This observation makes sense when you think of how the mechanics work. It also makes it interesting to think of how default is handled if internally the switch-case structure is evaluated recursively.

Knowing this tidbit, moving forward I’ll continue to set default as the final part of a switch-case structure. I’m familiar with its location last. Though when I’m feeling spicy, I may put it atop the structure — just to see whether anyone notices.

6 thoughts on “Fun with switch case, Part II

  1. The FSFʼs GCC compiler has a neat little trick up its sleeve in that itʼs possible—regrettably it never made it into the standard—to take the addresses of labels and use those addresses to later go-to them. (Clang also implemented this later on.)

    Relying on this language extension it would be possible to implement the above switch-case by relying on a jump table:

    #include <stdio.h>

    int main (void)
    { int a;

      printf (“1, 2, 3: “);
      scanf (“%d”,&a);

      /* switch-case jump table: */
      { void *case_addr [] = {&&case_1, &&case_2, &&case_3};

        /* Within range? Jump to case ‘a’! */
        if (a >= 1 && a <= 3)
          goto *case_addr [a-1];
        /* fall through! */

    /*default:*/
        puts (“You bad!”);
        goto switch_end;
      case_1:
        puts (“One!”);
        goto switch_end;
      case_2:
        puts (“Two!”);
        goto switch_end;
      case_3:
        puts (“Three!”);
        /* fall through! */
      switch_end:;
      }

      return (0);
    }

    Of course this is just for illustration purposes—where the language offers explicit support itʼs never a good idea to try to implement control structures with labels and goto.

    However, seeing that we can fall through to the default case if none of the case labels match, it might actually make sense to put default: first… that being said, I am (probably like most people) also one of those who always puts default: last.

  2. I tried that for this series and I couldn’t get it to work. But it makes sense as they’re labels. Imagine the obfuscated code you could write!

  3. I agree, this should only be used very sparingly, if at all… Peter Parkerʼs Uncle Ben comes to mind: With great power comes great responsibility! (Sorry, couldnʼt resist.)

  4. The coders who write the submissions to the IOCCC are marvelous. For the life of me, I can’t figure out how some of that stuff works. It’s just awesome!

  5. I know the feeling ☺

    Although I like to think of myself as a competent programmer, I fail to understand even ostensibly simple programs—like Brian Westleyʼs 1988ʼs winning entry westley.c to calculate . (A program with the nice property that the large one makes the circle, the more accurate the calculated result.)

    Not to speak of actually participating… for that I lack both the skill and, maybe even more importantly, the necessary creativity!

Leave a Reply