Part of C in 100s

C in 100 Seconds: Switch Statement | Episode 6

Celest KimCelest Kim

Video: C in 100 Seconds: Switch — case, break, default | Episode 6 by Taught by Celeste AI - AI Coding Coach

Take the quiz on the full lesson page
Test what you've read · interactive walkthrough

C Switch / Case

switch (value) { case X: ... break; default: ... }. Cleaner than long if-else chains for branching on a single value. Always include break unless you intentionally want fall-through.

switch is C's structured way of dispatching on integer values. Forget the break and you get fall-through bugs that haunt early C code.

The basic shape

#include <stdio.h>

int main() {
  int day = 3;

  switch (day) {
    case 1:
      printf("Monday\n");
      break;
    case 2:
      printf("Tuesday\n");
      break;
    case 3:
      printf("Wednesday\n");
      break;
    default:
      printf("Other day\n");
  }

  return 0;
}

Output: Wednesday.

The switch (day) evaluates day once. Each case N: is a label; execution jumps to the matching one. break exits the switch.

case labels are integer constants

switch (x) {
  case 1: ...           // OK
  case 1 + 2: ...       // OK (constant expression)
  case 'A': ...         // OK (char is an int)
  case some_var: ...    // ERROR — must be constant
  case 1.5: ...         // ERROR — no floats
}

case requires a compile-time constant integer expression. No variables, no floats, no strings. C++17 has if constexpr and pattern matching extensions; C does not.

Fall-through

Without break, execution falls through to the next case:

switch (grade) {
  case 'A':
  case 'B':
    printf("Good job\n");
    break;
  case 'C':
    printf("OK\n");
    break;
  default:
    printf("Try harder\n");
}

'A' falls through to 'B''s block. Useful for "multiple cases, one action."

But unintentional fall-through is a notorious bug source:

switch (cmd) {
  case 'q':
    quit = 1;          // forgot break!
  case 's':
    save();            // ALSO runs after 'q'
    break;
}

Modern compilers warn (-Wimplicit-fallthrough). C23 introduces [[fallthrough]]:

switch (cmd) {
  case 'q':
    quit = 1;
    [[fallthrough]];   // explicit; suppresses warning
  case 's':
    save();
    break;
}

For older C, the convention is a comment:

case 'q':
  quit = 1;
  /* fall through */
case 's':
  save();
  break;

default

switch (x) {
  case 1: ...; break;
  case 2: ...; break;
  default:
    // runs if no case matches
}

default is optional but recommended — without it, an unexpected value silently does nothing.

default doesn't have to be last (some codebases put it first), but convention is last.

switch vs if-else chain

// switch — clearer for many cases on one value
switch (day) {
  case 1: monday(); break;
  case 2: tuesday(); break;
  case 3: wednesday(); break;
  // ...
}

// if-else — clearer for ranges or multiple variables
if (score >= 90) ...
else if (score >= 80) ...
else if (age > 18 && score > 70) ...

Use switch for "match this exact value." Use if-else for ranges, multi-variable conditions, or non-integer comparisons.

switch is also faster on many compilers — they generate jump tables (one indirect branch) instead of sequential comparisons.

Variables in case bodies

A case body isn't a new scope by default. Declaring a variable inside is fine, but you need braces:

switch (x) {
  case 1: {           // braces start a block scope
    int y = 5;
    printf("%d\n", y);
    break;
  }
  case 2: {
    int y = 10;       // different y; OK because of braces
    printf("%d\n", y);
    break;
  }
}

Without braces, the second int y would clash. With braces, each case gets its own scope.

Range cases (GCC extension)

switch (grade_pct) {
  case 0 ... 59: printf("F\n"); break;       // GCC/Clang only
  case 60 ... 69: printf("D\n"); break;
  case 70 ... 79: printf("C\n"); break;
  case 80 ... 89: printf("B\n"); break;
  case 90 ... 100: printf("A\n"); break;
}

case A ... B: is a GCC/Clang extension — not portable. For portable code, use if-else chains for ranges.

Switch on chars

char c = 'a';
switch (c) {
  case 'a': case 'e': case 'i': case 'o': case 'u':
    printf("Vowel\n");
    break;
  default:
    printf("Consonant\n");
}

Chars are integers (1-byte) in C. Cases for 'a', 'e', etc. Multi-case fall-through is the idiom for "any of these."

Common mistakes

Forgetting break. Falls through to the next case. Compiler may warn; tests should catch. Always be explicit.

case "string":. Strings aren't integers. Switch only works on int-compatible values. For string dispatch, use a hash map or chained strcmps.

Variables without braces. case 1: int x = 5; errors because the declaration isn't in a block. Add { ... } around the body.

case with non-constant. case n: (where n is a variable) doesn't compile.

Ranges in standard C. case 1 ... 10: is GCC-only.

Ordering matters less. Unlike if-else, switch jumps directly. But matching cases all execute (if no break), in source order, after the first match.

What's next

Episode 7: while loops. while, do-while, and choosing between them.

Recap

switch (val) { case X: ... break; case Y: ... break; default: ... }. Cases must be compile-time integer constants. Forget break and you fall through. Use intentional fall-through (multiple cases with no body) for "any of these." default for "everything else." Wrap case bodies in { } if declaring variables inside. For ranges, use if-else (or GCC's case A ... B: extension).

Next episode: while loops.

Ready? Take the quiz on the full lesson page →
Test what you've learned. Watch the lesson and try the interactive quiz on the same page.