Peeter Joot's (OLD) Blog.

Math, physics, perl, and programming obscurity.

switch in C … confused by freeform text.

Posted by peeterjoot on October 2, 2009

I was surprised just now to learn (or relearn) a new variant of the C switch syntax looking at code today that I didn’t write (or I am particularly senile today).

I’d always written my case conditions in a scope, and had the break (if any) in that scope like so:

#include <stdio.h>

int main( int argc, char ** argv )
{
   switch (argc)
   {
      case 0:
      {
         printf( "can't get here: argc: %d\n", argc ) ;
         break ;
      }

      case 1:
      {
         printf( "1: argc: %d\n", argc ) ;
         break ;
      }

      default:
      {
         printf( "2: argc: %d\n", argc ) ;
      }
   }

   return 0 ;
}
hotel80:/vbs/engn/sqe> cc t.c
hotel80:/vbs/engn/sqe> a.out
1: argc: 1
hotel80:/vbs/engn/sqe> a.out 1
2: argc: 2
hotel80:/vbs/engn/sqe> a.out 1 blah
2: argc: 3

For some reason today I appear to have thought that the syntax HAD to be like:

case CONDITION:
STATEMENT_OR_SCOPE
case CONDITION:
STATEMENT_OR_SCOPE
...

Where STATEMENT_OR_SCOPE if it is a scope can contain an optional break. So today when I saw code like:

   switch (argc)
   {
      case 0:
      {
         printf( "can't get here: argc: %d\n", argc ) ;
      }
      break ;

      case 1:
      {
         printf( "1: argc: %d\n", argc ) ;
      }
      break ;

I thought … “how can that possibly work?” Can you ever get to case 1? Turns out the answer is yes, which makes sense in retrospect since the statements after a case don’t have to be in a scope.

Since I’ve put my breaks and everything else in the scope following the case for so many years and never deviating from that practice I got confused when I saw otherwise.

If the code had been written:

   switch (argc)
   {
      case 0:

         printf( "can't get here: argc: %d\n", argc ) ;
         break ;

      case 1:

         printf( "1: argc: %d\n", argc ) ;
         break ;

… I don’t think I would have gotten confused (ie. if you are going to use a scope for your case statements doesn’t it make sense to put the break in there too?) It’s funny how much a little deviation from convention makes a difference in understanding program flow.

Personally it seems to me that a scope following a case really ought to be mandatory. It’s a tiny bit more typing, but I think the clarity is worth it. I’m probably getting spoiled by perl, where the scope is mandatory.

3 Responses to “switch in C … confused by freeform text.”

  1. Hasan Murtaza said

    I learned this behaviour early on a few years ago, so it never caused me any angst. Basically, the whole switch-case construct owes more to languages like cobol and pascal than to C, so the semantics seems a little out of place within C.

    The only thing that matters as far as control flow goes, are the case statements themselves. Any squiggly brackets you use only have the effect of defining a new stack frame, and limiting the scope of variables defined within them. The switch- case statements can also be thought of as as sequence of GOTO statements, and that is why they have : colons at the end of them, as if they were labels. The break is just a jump to the end of the switch statement, so you see, the whole concept of stack frames has very little place in that context.

    If the case statements had been inspired by the C language, they would have been just like if statements: forced you to use brackets for multi-line case statements, while a single line statement without brackets would have had an implicit break at the end of it.

  2. “… written my case conditions in a scope.” You are thinking about this using the wrong concepts (easy enough to do given C’s idiosyncratic handling of switch). The case is a label and like all labels can prefix any statement, so you can write:


    switch (x)
    {
    case 1: if (y)
    case 2: z--;
    else
    case 3: z++;
    }

    And { } is a compound statement, which is a block, which starts a new scope.

    More technical details here.

Leave a comment