[This section corresponds to K&R Sec. 3.4]
A frequent sort of pattern is exemplified by the sequence
if(x == e1) /* some code */ else if(x == e2) /* other code */ else if(x == e3) /* some more code */ else if(x == e4) /* yet more code */ else /* default code */Depending on the value of x, we have one of several chunks of code to execute, which we select with a long if/else/if/else... chain. When the value we're selecting on is an integer, and when the values we're selecting among are all constant, we can use a switch statement, instead. The switch statement evaluates an expression and matches the result against a series of ``case labels''. The code beginning with the matching case label (if any) is executed. A switch statement can also have a default case which is executed if none of the explicit cases match.
A switch statement looks like this:
switch( expr ) { case c1 : ... code ... break; case c2 : ... code ... break; case c3 : ... code ... break; ... default: ... code ... break; }The expression expr is evaluated. If one of the case labels (c1, c2, c3, etc., which must all be integral constants) matches, execution jumps to there, and continues until the next break statement. Otherwise, if there is a default label, execution jumps to there (and continues to the next break statement). Otherwise, none of the code in the switch statement is executed. (Yes, the break statement is also used to break out of loops. It breaks out of the nearest enclosing loop or switch statement it finds itself in.)
The switch statement only works on integral arguments and expressions (char, the various sizes of int, and enums, though we haven't met enums yet). There is no direct way to switch on strings, or on floating-point values. The target case labels must be specified explicitly; there is no general way to specify a case which corresponds to a range of values.
One peculiarity of the switch statement is that the break at the end of one case's block of code is optional. If you leave it out, control will ``fall through'' from one case to the next. Occasionally, this is what you want, but usually not, so remember to put a break statement after most cases. (Since falling through is so rare, many programmers highlight it, when they do mean to use it, with a comment like /* FALL THROUGH */, to indicate that it's not a mistake.) One way to make use of ``fallthrough'' is when you have a small set or range of cases which should all map to the same code. Since the case labels are just labels, and since there doesn't have to be a statement immediately following a case label, you can associate several case labels with one block of code:
switch(x) { case 1: ... code ... break; case 2: ... code ... break; case 3: case 4: case 5: ... code ... break; default: ... code ... break; }Here, the same chunk of code is executed when x is 3, 4, or 5.
The case labels do not have to be in any particular order; the compiler is smart enough to find the matching one if it's there. The default case doesn't have to go at the end, either.
It's common to switch on characters:
switch(c) { case '+': /* code for + */ break; case '-': /* code for - */ break; case '\n': /* code for newline */ /* FALL THROUGH */ case ' ': case '\t': /* code for other whitespace */ break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': /* code for digits */ break; default: /* code for all other characters */ break; }It's also common to have a set of #defined values, and to switch on those:
#define APPLE 1 #define ORANGE 2 #define CHERRY 3 #define BROCCOLI 4 ... switch(fruit) { case APPLE: printf("turnover"); break; case ORANGE: printf("marmalade"); break; case CHERRY: printf("pie"); break; case BROCCOLI: printf("wait a minute... that's not a fruit"); break; }
Read sequentially: prev next up top
This page by Steve Summit // Copyright 1996-1999 // mail feedback