Why Not Just Use if/else?
You can do everything switch/case does with if/else chains. The difference is clarity. When you are checking one variable against five, six, or ten specific values, if/else turns into a wall of repetitive code that is hard to scan visually. switch/case lines up your options so you can see them all at a glance.
Use if/else when: you are testing ranges (if (temp > 30)), combining conditions with && or ||, or comparing different variables.
Use switch/case when: you are comparing one variable against a list of exact values.
Basic Syntax
switch (variable) {
case value1:
// code for value1
break;
case value2:
// code for value2
break;
default:
// code if nothing matched
break;
}
A few rules to know:
- The variable inside
switch()must be an integer type:int,byte,char, orlong. You cannot usefloat,double, orString. - Each
casevalue must be a constant (a number, a character literal like'A', or aconstvariable). You cannot use variables as case values. - The
defaultcase handles anything that did not match. Always include it.
The break Keyword
break tells the program to exit the switch block. Without it, execution falls through to the next case and keeps running. This is the single most common source of switch/case bugs.
Here is what fall-through looks like:
int mode = 1;
switch (mode) {
case 1:
Serial.println("Mode 1");
// no break here!
case 2:
Serial.println("Mode 2");
// no break here either!
case 3:
Serial.println("Mode 3");
break;
}
When mode is 1, this prints:
Mode 1
Mode 2
Mode 3
All three lines print because the code falls through from case 1 into case 2 and then into case 3.
What it looks like when you hit this bug: Your DIP switch is in position 1 but the behavior matches position 3. Or your keypad reads 'A' but the code runs the actions for 'A', 'B', and 'C' all at once.
When Fall-Through Is Actually Useful
Sometimes you want multiple cases to share the same code:
switch (key) {
case '1':
case '2':
case '3':
Serial.println("Number key pressed");
break;
case '#':
Serial.println("Submit");
break;
}
Cases 1, 2, and 3 have no code and no break, so they all fall through to the Serial.println line. This is intentional and saves you from writing the same code three times.
Using switch with digitalRead (DIP Switch Positions)
A 3-position DIP switch gives you 8 possible combinations (2^3 = 8). Read the three pins and combine them into a single number:
int position = 0;
if (digitalRead(SW1_PIN) == HIGH) position += 1;
if (digitalRead(SW2_PIN) == HIGH) position += 2;
if (digitalRead(SW3_PIN) == HIGH) position += 4;
switch (position) {
case 0: /* all OFF */ break;
case 1: /* SW1 only */ break;
case 2: /* SW2 only */ break;
// ... and so on up to case 7
}
Using switch with Analog Ranges
switch/case only works with exact values, but analog readings come in a range (0 to 1023). The trick is to map the range into zones first:
int raw = analogRead(A0);
int zone = map(raw, 0, 1023, 0, 4); // 5 zones: 0,1,2,3,4
switch (zone) {
case 0: Serial.println("Very low"); break;
case 1: Serial.println("Low"); break;
case 2: Serial.println("Medium"); break;
case 3: Serial.println("High"); break;
case 4: Serial.println("Very high"); break;
default: Serial.println("Out of range"); break;
}
Using switch with Keypad Characters
The Keypad library returns a char. Since char is an integer type under the hood, it works perfectly with switch:
char key = keypad.getKey();
if (key) {
switch (key) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
handleDigit(key);
break;
case '*':
clearEntry();
break;
case '#':
submitCode();
break;
case 'A':
armSystem();
break;
default:
Serial.println("Unknown key");
break;
}
}
The default Case
Always include default, even if you think you have covered every possibility:
- Debugging. If a value you did not expect shows up,
defaultcan print a warning. - Safety. Hardware glitches can produce unexpected readings.
- Future-proofing. If you add new modes later and forget to add a case,
defaultcatches it.
default:
Serial.print("ERROR: unexpected value: ");
Serial.println(mode);
break;
Common Mistakes
| Mistake | What Happens | Fix | |---------|-------------|-----| | Forgetting break | Code falls through into the next case | Add break; at the end of every case unless you want fall-through | | Using a String | Compiler error: "switch quantity not an integer" | Use char for single characters, or use if/else for String comparisons | | Using a float | Compiler error or unexpected behavior | Convert to int first with (int) or map() | | Using == instead of case | Syntax error | The syntax is case 3: not case == 3: | | Using a variable as a case value | Compiler error: "case label does not reduce to an integer constant" | Case values must be constants | | Missing the default case | Unhandled values silently do nothing | Always add a default |