Names specified here
Name Description Notes Source Availability
break Exit from switch statement L Keyword C89 C90 C95 C99 C11
case Branch in switch statement L Keyword C89 C90 C95 C99 C11
default Default branch in switch statement L Keyword C89 C90 C95 C99 C11
switch Select from alternative values L Keyword C89 C90 C95 C99 C11

A switch statement chooses an action based on the value of a controlling expression:

statement
switch-labelled-statement
selection-statement
switch ( expression ) statement
switch-labelled-statement
case constant-expression : statement
default : statement
jump-statement
break ;

In practice, the controlled statement is always a block:

switch (expression) {
  . . .
}

When a switch is executed, the expression is evaluated, and its value causes a jump to a defined point within the statement. Such points are marked by labels, which take one of the following forms:

case constant-expression:
default:

If the value of the expression of one of the case labels matches the value of the controlling expression of the switch, execution jumps to that point. Otherwise, it jumps to the default label if it exists, or it exits the switch statement altogether. Within the statement, execution continues until it reaches the end (even if it falls through a following label), or reaches a break statement. In practice, often every label except the first is preceded by a break statement, so the enclosed statement is divided up into discrete groups. For example:

switch (mark) {
  case 'A':
    printf("Well done!\n");
    break;

  case 'B':
    printf("Good effort.\n");
    break;

  case 'C':
    printf("Not bad.\n");
    break;

  case 'D':
    printf("Try harder.\n");
    break;

  case 'E':
    printf("Pathetic!\n");
    break;

  case 'F':
    printf("Loser!\n");
    break;

  default:
    printf("ERROR\n");
    break;
}

All label values in the same switch must be distinct. Labels can be grouped together if their distinct values are supposed to produce identical behaviour:

switch (mark) {
  case 'A':
  case 'B':
  case 'C':
    printf("Pass\n");
    break;

  case 'D':
  case 'E':
  case 'F':
    printf("Fail\n");
    break;

  default:
    printf("ERROR\n");
    break;
}

It's good practice to add a redundant break to the last group. If every group has a break, they can be freely re-ordered for readability, without changing the meaning.

switch (mark) {
  default:
    printf("ERROR\n");
    break;

  case 'A':
  case 'B':
  case 'C':
    printf("Pass\n");
    break;

  case 'D':
  case 'E':
  case 'F':
    printf("Fail\n");
    break;
}

When multiple switches and loops are nested, each break applies to the innermost construct containing it.

Comparison with if

switch often serves as an alternative to if. Our first example is equivalent to the following:

if (mark == 'A') {
  printf("Well done!\n");
} else if (mark == 'B') {
  printf("Good effort.\n");
} else if (mark == 'C') {
  printf("Not bad.\n");
} else if (mark == 'D') {
  printf("Try harder.\n");
} else if (mark == 'E') {
  printf("Pathetic!\n");
} else if (mark == 'F') {
  printf("Loser!\n");
} else {
  printf("ERROR\n");
}

This if happens to be shorter than the switch, but it can appear more cluttered, with } else if (mark == being repeated several times. The second example is equivalent to the following:

if (mark == 'A' || mark == 'B' || mark == 'C') {
  printf("Pass\n");
} else if (mark == 'D' || mark == 'E' || mark == 'F') {
  printf("Fail\n");
} else {
  printf("ERROR\n");
}

…which still has a lot of repetition, as well as longer lines to manage. switch can also look better when the controlling expression is not a simple variable:

switch (get_mark(student_id)) {
  case 'A':
    printf("Well done!\n");
    break;

  . . .
}

The equivalent if is not necessarily:

if (get_mark(student_id) == 'A') {
  printf("Well done!\n");
} else if (get_mark(student_id) == 'B') {
  . . .
}

…because get_mark(student_id) is now invoked multiple times, and might have side-effects, or be computationally expensive. It would be much better to store its result:

{
  int mark = get_mark(student_id);
  if (mark == 'A') {
    printf("Well done!\n");
  } else if (mark == 'B') {
    . . .
  }
}

Not all if chains can be represented by an alternative switch. For example, these ifs classify a score using inequalities:

if (score < 10) {
  printf("Why did you bother?\n");
} else if (score > 90) {
  printf("Excellent!\n");
} else {
  printf("Mediocre.\n");
}

Even if the score has a discrete set of values, so that you could write the code as a switch, it would have poor readability.

One problem with choosing to use switch is then later deciding to make the test more sophisticated, and thus discovering that you need an if.


CHaR
Sitemap Supported
Site format updated 2024-06-05T22:37:07.391+0000
Data updated 1970-01-01T00:00:00.000+0000
Page updated 2022-06-17T21:43:05.000+0000