Skip to content
Theory · Conditions · lesson 3 of 6

switch and fall-through

A big building has a directory in its lobby: "Accounts: floor 3, HR: floor 5, canteen: floor 1." You don't walk every floor in turn. You find your line in the directory and take the lift straight to the right floor.

An else if chain is like walking every floor. When one variable is compared with several numbers, an else if chain compares that same variable with a new number in every branch. A switch statement works like the lobby directory: it evaluates the expression in parentheses once and jumps to the branch with the same value:

C++
#include <iostream>

int main() {
    int day = 2;
    switch (day) {
        case 1:
            std::cout << "Monday\n";
            break;
        case 2:
            std::cout << "Tuesday\n";  // Tuesday
            break;
        default:
            std::cout << "another day\n";
    }
}

Let's walk through the program:

  1. switch (day) evaluates day and gets 2.
  2. Execution jumps straight to the case 2: label and prints Tuesday.
  3. break ends the switch, so default is never reached.

The case and default labels

A case with a constant and a colon is a label: where execution jumps when the expression equals that constant. In the lobby directory, a label is the line with a floor number.

  • break ends the switch.
  • The default label runs when no case label matches.
  • When no label matches and there is no default, no branch runs.

Which values fit

A switch has some limits:

  • the expression in a switch must have an integer type: int and char fit, while double does not;
  • a case takes a constant known at compile time: a literal such as 2 or 'a', or a constexpr variable;
  • two labels with the same value do not compile.

A switch checks only for equality. A condition such as day > 5 cannot be written as a label, so ranges still need an else if chain.

Fall-through

This is where the lift analogy ends. A lift stops at your floor, while a switch without break keeps going.

A label does not end the code that comes before it. Without break, execution goes on through every following label, default included, until a break or the end of the switch. This is called fall-through.

Step through the program and watch where execution enters the switch and where it leaves:

LiveFall-through without breakstep 1 of 8 · frames: 1

The variable level is 2

The highlighted line is the one that runs on this step

Fall-through lets several labels share one branch:

C++
char c = 'e';
switch (c) {
    case 'a':
    case 'e':
    case 'o':
        std::cout << "vowel\n";  // vowel
        break;
    default:
        std::cout << "other\n";
}

When c is 'e', execution jumps to the case 'e': label, passes the empty case 'o': label, and the program prints vowel. A letter that has no label goes to default.

If a branch has code of its own before the next label, an intended fall-through is marked with the line [[fallthrough]];. It does not change what the program does. It tells the compiler and the reader that the missing break is intended:

C++
int level = 2;
switch (level) {
    case 2:
        std::cout << "admin ";
        [[fallthrough]];
    case 1:
        std::cout << "user\n";  // admin user
        break;
}

Let's look at both cases:

  1. When level is 2, the program prints admin , falls through into case 1: and prints user after it. The result is admin user.
  2. When level is 1, execution starts at case 1:, and the program prints only user.

Common mistake

A branch is missing its break:

C++
int day = 1;
switch (day) {
    case 1:
        std::cout << "Monday\n";  // ✗
    case 2:
        std::cout << "Tuesday\n";
        break;
}
TEXT
warning: unannotated fall-through between switch labels [-Wimplicit-fallthrough]

When day is 1, the program prints both Monday and Tuesday: execution falls through into case 2. Clang warns about this only with the -Wimplicit-fallthrough flag, while GCC already warns with -Wextra. End every branch with break, and mark an intended fall-through with [[fallthrough]]. What a switch without break prints is a common interview question.

Key points

  • A switch evaluates the expression once and jumps to the case label with the same value, or to default when there is none.
  • The expression in a switch has an integer type, and a case takes a constant known at compile time.
  • Without break, execution falls through the following labels until a break or the end of the switch.
  • An intended fall-through is marked with [[fallthrough]];.

Subscribe to take the course

The course is free. Sign in with Telegram and subscribe to the channel to open every lesson.

Sign in another way