C switch Statement
Updated 7 min read Aimerscrew
Some decisions are really one question with many fixed answers: which button was pressed, which menu option was chosen, which day of the week it is. The C switch statement handles exactly this kind of choice. In this lesson, you'll learn how switch, case, break and default work together, and how to avoid the "fall-through" bug that surprises almost everyone the first time.
🌍 Real-life example
A vending machine doesn't run through a list of "is it A? is it B? is it C?" questions in your head. You press B and it goes straight to slot B. A switch works the same way: it takes one value and jumps directly to the matching case.
What is a switch statement in C?
A switch statement picks one of several blocks of code based on the value of a single integer expression. Here's the general shape:
switch (expression) {
case VALUE_1:
// statements for VALUE_1
break;
case VALUE_2:
// statements for VALUE_2
break;
default:
// statements when nothing matched
break;
}
switch (expression): the value being tested, such as a variable.case VALUE:: a label. If the expression equals this value, execution starts here.break;: jumps out of the switch, to the first line after its closing brace.default:: optional; runs when no case matches, like the finalelsein an if chain.
A first example: days of the week
#include <stdio.h>
int main(void) {
int day = 3;
switch (day) {
case 1:
printf("Monday\n");
break;
case 2:
printf("Tuesday\n");
break;
case 3:
printf("Wednesday\n");
break;
case 4:
printf("Thursday\n");
break;
case 5:
printf("Friday\n");
break;
case 6:
printf("Saturday\n");
break;
case 7:
printf("Sunday\n");
break;
default:
printf("Not a valid day\n");
break;
}
return 0;
}
Wednesday
C evaluates day once, jumps to case 3:, prints Wednesday, and the break sends it out of the switch. Try day = 9 and you'll see Not a valid day.
What can a case label be?
Case labels have strict rules:
- They must be integer constants: numbers like
3, characters like'B'(acharis a small integer), or names created with#define, which you met in C constants. - They can't be variables, ranges (
case score >= 90:is not allowed), decimal numbers or strings. - Two cases in the same switch can't have the same value. GCC reports
duplicate case value.
Because characters count as integers, switch is perfect for a vending machine keypad:
#include <stdio.h>
int main(void) {
char button = 'B';
switch (button) {
case 'A':
printf("Water - $1.25\n");
break;
case 'B':
printf("Orange juice - $2.50\n");
break;
case 'C':
printf("Chips - $1.75\n");
break;
default:
printf("Unknown button, please try again\n");
break;
}
return 0;
}
Orange juice - $2.50
What happens if you forget break? (fall-through)
A case label only marks where execution starts. It doesn't mark where it stops. Without a break, C keeps going straight into the next case's code, and the next, until it reaches a break or the end of the switch. This is called fall-through.
Here's a bank menu where every break was forgotten. The user chose option 2:
#include <stdio.h>
int main(void) {
int choice = 2;
switch (choice) {
case 1:
printf("Checking balance...\n");
case 2:
printf("Depositing money...\n");
case 3:
printf("Withdrawing money...\n");
default:
printf("Goodbye!\n");
}
return 0;
}
Depositing money...
Withdrawing money...
Goodbye!
The program jumped to case 2 correctly, then fell through cases 3 and default as well. The customer wanted to deposit, but the program also "withdrew" money. GCC catches this with -Wextra: warning: this statement may fall through.
Grouping cases that share code
Fall-through has a useful side. When several values need the same code, stack their labels on top of each other. Empty labels fall through to the shared code, and GCC doesn't warn about this pattern:
#include <stdio.h>
int main(void) {
int day = 6;
switch (day) {
case 1:
case 2:
case 3:
case 4:
case 5:
printf("Weekday: the gym opens at 6 AM.\n");
break;
case 6:
case 7:
printf("Weekend: the gym opens at 8 AM.\n");
break;
default:
printf("Invalid day number.\n");
break;
}
return 0;
}
Weekend: the gym opens at 8 AM.
Using fall-through on purpose
Sometimes falling through is exactly what you want. In an airline loyalty program, a gold member gets every silver perk plus more, and a silver member gets every bronze perk plus more. Start at the member's tier and let execution fall down through the lower tiers:
#include <stdio.h>
int main(void) {
int tier = 2; /* 1 = bronze, 2 = silver, 3 = gold */
printf("Your perks:\n");
switch (tier) {
case 3:
printf("- Free airport lounge access\n");
/* fall through */
case 2:
printf("- Free checked bag\n");
/* fall through */
case 1:
printf("- Priority boarding\n");
break;
default:
printf("- No perks yet\n");
break;
}
return 0;
}
Your perks:
- Free checked bag
- Priority boarding
The /* fall through */ comment tells other programmers (and GCC, which recognizes it and stays quiet) that the missing break is intentional.
💡 Tip
Always put a break after the last case and after default too, even though nothing comes below them. If someone adds a new case later, they won't create an accidental fall-through.
Real-world example: a simple calculator
A switch on an operator character is a classic way to build a calculator. Notice that a case can contain any code, including an if statement:
#include <stdio.h>
int main(void) {
double a = 12.0;
double b = 4.0;
char op = '/';
switch (op) {
case '+':
printf("%.1f + %.1f = %.1f\n", a, b, a + b);
break;
case '-':
printf("%.1f - %.1f = %.1f\n", a, b, a - b);
break;
case '*':
printf("%.1f * %.1f = %.1f\n", a, b, a * b);
break;
case '/':
if (b != 0.0) {
printf("%.1f / %.1f = %.1f\n", a, b, a / b);
} else {
printf("Cannot divide by zero.\n");
}
break;
default:
printf("Unknown operator: %c\n", op);
break;
}
return 0;
}
12.0 / 4.0 = 3.0
You'll turn this into a full interactive program in the calculator project.
switch vs if else: which should you use?
| Situation | Best choice |
|---|---|
| One integer or char compared against many exact values | switch |
Ranges, like score >= 90 | if / else if |
Decimal numbers (double, float) or strings | if / else if |
| Conditions on several different variables | if / else if |
| Several values sharing the same code | switch with grouped cases |
Anything a switch does, an if else chain can do too. A switch is simply cleaner when you're matching one value against a menu of options, and compilers can often turn it into a fast jump table.
Common mistakes with switch
1. Forgetting break
The most common switch bug by far. Unless you're grouping cases or falling through on purpose (with a comment), every case should end with break.
2. Using a range or a variable as a label
switch (score) {
case score >= 90: // error: not a constant
printf("A\n");
break;
}
Case labels must be fixed integer values known when the program is compiled. Use an if else chain for ranges.
3. Switching on a string or a double
switch (name) where name holds text, or switch (price) where price is a double, won't compile. GCC says switch quantity not an integer.
4. Declaring a variable right after a case label
Before C23, a label had to be followed by a statement, not a declaration, so case 1: int total = 0; is rejected or warned about by many compilers. It also creates a variable that every later case can see. Wrap the case's code in braces instead: case 1: { int total = 0; ... break; }.
Practice exercise
🏋️ Try it yourself
A parking garage charges by vehicle type: 'M' (motorcycle) pays $3, 'C' (car) pays $8, and 'T' (truck) pays $15. Lowercase letters should work too. Store the type in a char (try 'c') and print the fee, or Unknown vehicle type for anything else.
Show solution
#include <stdio.h>
int main(void) {
char vehicle = 'c';
switch (vehicle) {
case 'M':
case 'm':
printf("Motorcycle: $3\n");
break;
case 'C':
case 'c':
printf("Car: $8\n");
break;
case 'T':
case 't':
printf("Truck: $15\n");
break;
default:
printf("Unknown vehicle type\n");
break;
}
return 0;
}
Car: $8
What's next?
For a quick choice between just two values, there's an even shorter tool than if else. Next, learn the C ternary operator.
Key takeaways
- A switch compares one integer expression against constant case labels and jumps to the match.
- Case labels must be integer constants such as 3, 'B' or a #define name; no ranges, variables, doubles or strings.
- break exits the switch; without it, execution falls through into the next case.
- default runs when no case matches, like the final else in an if chain.
- Stack several case labels to share one block of code, and mark intentional fall-through with a comment.
- Use switch for exact matches on one value and if else for ranges or complex conditions.
Frequently asked questions
What happens if there is no break in a switch case in C?
Execution continues into the next case's code, and the one after that, until a break or the end of the switch. This is called fall-through. GCC warns about it with -Wextra unless a fall through comment marks it as intentional.
Can you use a string in a C switch statement?
No. The switch expression and case labels must be integers, and characters count as integers. To choose based on text, use an if else chain with strcmp().
Is default required in a switch statement?
No, default is optional. If it is missing and no case matches, the switch simply does nothing. Including a default is good practice for catching unexpected values.
Is switch faster than if else in C?
Often slightly, because the compiler can turn a switch with many cases into a jump table. For beginners, readability matters more: use switch when you match one value against many exact options.
Can two case labels have the same value?
No. Each case value in a switch must be unique, otherwise GCC reports a duplicate case value error.