lp0 on fire

My personal blog

C89-Goto: Switch-case

In my previous article I explained how the goto statement can be used to emulate loop control structures. This time I'll quickly demonstrate how goto can be used to emulate the switch-case control structure. It is shown here for educational purpose only, I doubt anyone is waiting to see this in their production code unless the language only has support for if-else and goto.

Alright, loops are not a big deal. But what about switch-case? We're gonna implement a not too difficult one, which contains fallthrough and a default statement as well.

/*  switch-case: statement */

int i = 0;

switch (i)
{
    case 1:
        printf("Case: 1");
        break;

    case 2:
    case 3:
        printf("Case: 2");
        break;

    default:
        printf("Case: none");
        break;
}

The execution flow is pretty simple:

  1. if i is 1: print "Case: 1" and terminate switch-case
  2. if i is 2 or 3: print "Case: 2" and terminate switch-case
  3. if i isn't 1, 2 or 3: print "Case: none" and terminate switch-case

Here's how to implement this in goto:

/* switch-case: goto */

int i = 1;

if (i == 1) goto case_1;
if (i == 2) goto case_2;
if (i == 3) goto case_2;
goto case_default;

case_1:
printf("Case: 1");
goto switch_end;

case_2:
printf("Case: 2");
goto switch_end;

case_default:
printf("Case: none");
goto switch_end;

switch_end:

The code structure is again a fair bit flatter than a normal switch-case. Another interesting observation is that we first define where to jump to for which values, and then below define how to handle each case.

The overall code could be smaller if we handled the default case at the top (to eliminate the goto case_default;) and remove the goto switch_end; from the last case since it will already continue correctly without jump. We could also list all options for goto case_2; in one go. While it is more compact, the overall code becomes harder to read as it's less verbose.

/* switch-case: goto */

int i = 1;

if (i == 1) goto case_1;
if (i == 2 || i == 3) goto case_2;

printf("Case: none");
goto switch_end;

case_1:
printf("Case: 1");
goto switch_end;

case_2:
printf("Case: 2");

switch_end:

Sure we could implement this as an if-else block as well, but I think it doesn't look as nice if there would be many more cases than we currently have:

/*  switch-case: if-else */

int i = 0;

if (i == 1)
{
    printf("Case: 1");
}
else if (i == 2 || i == 3)
{
    printf("Case: 2");
}
else
{
    printf("Case: none");
}

Conclusion

Hopefully you now understand how switch-case can be emulated using the goto statement and with the if-else control structure. In the next article I'll explain how goto can be used to emulate exceptions and use it for resource cleanup (such as memory allocations).