# Switch statement

> Mediated Wiki article. Canonical URL: https://mediated.wiki/source/Switch_statement
> Markdown URL: https://mediated.wiki/source/Switch_statement.md
> Source: https://en.wikipedia.org/wiki/Switch_statement
> Source revision: 1347651368
> License: Creative Commons Attribution-ShareAlike 4.0 International (https://creativecommons.org/licenses/by-sa/4.0/)

{{short description |Programming statement for branching control based on a value}}
{{more citations needed |date=April 2013}}
{{Use American English |date=December 2024}}

In [computer programming](/source/computer_programming), a '''switch statement''' is a selection [control flow](/source/control_flow) mechanism that changes execution control based on the value of an [expression](/source/expression_(computer_science)) (i.e. evaluation of a [variable](/source/variable_(computer_science))). A switch statement is similar to an [if statement](/source/if_statement) but instead of branching only on true or false, it branches on any number of values. Although the syntax varies by [programming language](/source/programming_language), most [imperative](/source/imperative_programming) languages provide a statement with the [semantics](/source/semantics_(computer_science)) described here as the switch statement. Often denoted with the [keyword](/source/keyword_(computer_programming)) {{code|switch}}, some languages use variations such as {{code|case}}, {{code|select}}, or {{code|inspect}}.

==Value==
Sometimes, use of a switch statement is considered superior to an equivalent series of if-then-else statements because it is:

; Easier to understand: And consequently easier to maintain: at least partially since it's fixed depth.

; Easier to debug: For example, setting breakpoints on code vs. a call table, if the debugger has no conditional breakpoint capability.

; Easier to verify: that all values are handled since a compiler can warn if a value is not handled.

; Can execute faster: An [optimized](/source/optimization_(computer_science)) implementation may execute much faster because it is often implemented as a [branch table](/source/branch_table).<ref>{{cite book |last1=Guntheroth |first1=Kurt |title=Optimized C++ |date=April 27, 2016 |publisher=O'Reilly Media |isbn=9781491922033 |page=182}}</ref> When implemented as such, a switch statement embodies a [perfect hash](/source/perfect_hash).

: An [optimizing compiler](/source/optimizing_compiler) such as [GCC](/source/GNU_Compiler_Collection) or [Clang](/source/Clang) may compile a switch statement into either a [branch table](/source/branch_table) or a [binary search](/source/binary_search).<ref>Vlad Lazarenko. [https://web.archive.org/web/20220313040503/http://lazarenko.me/switch/ From Switch Statement Down to Machine Code]</ref> A branch table allows the program to determine which branch to execute with a single calculation instead of comparing values in a sequence. A binary search takes only a logarithmic number of comparisons, measured in the number of cases in the switch statement. Generally, the only way to determine whether the code was optimized in this way, is by analyzing the compiler output such as [assembly](/source/Assembly_language) or [machine code](/source/machine_code).

; Less complex: In terms of a [control-flow graph](/source/control-flow_graph), a switch statement consists of two nodes (entrance and exit), plus one edge between them for each option. By contrast, a sequence of if-then-else statements has an additional node for every case other than the first and last, together with a corresponding edge. The resulting control-flow graph for the sequences of "if"s thus has many more nodes and almost twice as many edges, without adding useful information.

==Elements==
Typically, a switch statement involves:

; Verb: Starts with a control verb such as {{code|select}} which is followed by an expression which is often a variable name; the ''control expression'' or ''control variable''.

; Cases: Subsequent branch alternative sections each start with a keyword (i.e. {{code|case}}) plus a value (or multiple values) along with code to execute for the value(s). In some languages, i.e. [PL/I](/source/PL%2FI) and [Rexx](/source/Rexx), if the control expression is omitted then each alternative begins with a {{code|when}} clause containing a Boolean expression and a match occurs for the first case for which that expression evaluates true; similar to an if-then-else structure.

: In a language with fall through behavior, such as C, each section ends with a keyword (such as {{code|break}}) if that section should ''not'' fall through.

; Default: An optional default case is typically allowed, often via a keyword such as {{code|default}}, {{code|otherwise}}, or {{code |else}}. Control branches to this section when none of the other cases match the control expression. In some languages, such as C, if no case matches and the default section is omitted, the statement does nothing, but in others, like PL/I, an error occurs.

== <span class="anchor" id="Fallthrough"></span> Fall through ==
Two main variations of the switch statement include ''unstructured'' which supports '''fall through''' and ''structured'' which does not.

For a structured switch, as in [Pascal](/source/Pascal_(programming_language))-like languages, control jumps from the start of the switch statement to the selected case and at the end of the case, control jumps to the end of the switch statement. This behaves like an if–then–else [conditional](/source/Conditional_(computer_programming)) but supports branching on more than just true and false values. To allow multiple values to execute the same code (avoiding [duplicate code](/source/duplicate_code)), the syntax permits multiple values per case.

An unstructured switch, as in [C](/source/C_(programming_language)) (and more generally languages influenced by Fortran's [computed goto](/source/computed_goto)), acts like [goto](/source/goto). Control branches from the start of the switch to a case section and then control continues until either a block exit statement or the end of the switch statement. When control branches to one case, but continues into the subsequent branch, the control flow is called ''fall through'', and allows branching to the same code for multiple values.

Fall through is prevented by ending a case with a keyword (i.e. {{code|break}}), but a common mistake is to accidentally omit the keyword, causing unintentional fall through and often a [bug](/source/bug_(engineering)). Therefore, many consider this language feature to be dangerous,<ref>van der Linden, Peter (1994). ''Expert C Programming: Deep C Secrets'', p. 38. Prentice Hall, Eaglewood Cliffs. {{ISBN|0131774298}}.</ref> and often fall through code results in a warning from a code quality tool such as [lint](/source/Lint_(software)).

Some languages, such as [JavaScript](/source/JavaScript), retain fall through semantics, while others exclude or restrict it. Notably, in C# all blocks must be terminated with {{code|break}} or {{code|return}} unless the block is empty which limits fall through only for branching from multiple values.

In some cases, languages provide optional fall through. For example, [Perl](/source/Perl) does not fall through by default, but a case may explicitly do so using a {{code|continue}} keyword, preventing unintentional fall through. Similarly, [Bash](/source/Bash_(Unix_shell)) defaults to not falling through when terminated with {{code|;;}}, but allows fall through<ref>since [http://git.savannah.gnu.org/cgit/bash.git/tree/NEWS?id=3185942a5234e26ab13fa02f9c51d340cec514f8#n111 version 4.0], released in 2009.</ref> with {{code|;&}} or {{code|;;&}} instead.

An example of a switch statement that relies on fall through is [Duff's device](/source/Duff's_device).

==Case expression evaluation==
Some languages allow for a complex case expression (not just a static value), allowing for more dynamic branching behavior. This prohibits certain compiler optimizations, so is more common in dynamic languages where flexibility is prioritized over performance.

For example, in [PHP](/source/PHP) and [Ruby](/source/Ruby_(programming_language)), a constant can be used as the control expression, and the first case statement that evaluates to match that constant is executed. In the following PHP code, the switch expression is simply the true value, so the first case expression that is true is the one selected.

<syntaxhighlight lang="php">
switch (true) {
    case ($x == 'hello'):
        foo();
        break;
    case ($z == 'howdy'): break;
}
</syntaxhighlight>

This feature is also useful for checking multiple variables against one value rather than one variable against many values.

<syntaxhighlight lang="php">
switch (5) {
    case $x: break;
    case $y: break;
}
</syntaxhighlight>

COBOL also supports this form via its <code>EVALUATE</code> statement. PL/I supports similar behavior by omitting the control expression, and the first <code>WHEN</code> expression that evaluates as true is executed.

In Ruby, due to its handling of <code>===</code> equality, the case expression can be used to test a variable's class. For example:

<syntaxhighlight lang="ruby">
case input
when Array then puts 'input is an Array!'
when Hash then puts 'input is a Hash!'
end
</syntaxhighlight>

==Result value==
Some languages support evaluating a switch statement to a value.

===Case expression===
The ''case expression'' is supported by languages dating at least as far back as [ALGOL-W](/source/ALGOL-W).<ref name="Wirth">{{cite journal |last1=Wirth |first1=Niklaus |author1-link=Niklaus Wirth |last2=Hoare |first2=C. A. R. |author2-link=Tony Hoare |date=June 1966 |title=A contribution to the development of ALGOL |url=https://dl.acm.org/doi/10.1145/365696.365702 |journal=Communications of the ACM |volume=9 |issue=6 |pages=413–432 |doi=10.1145/365696.365702 |s2cid=11901135 |via=[Association for Computing Machinery](/source/Association_for_Computing_Machinery) |access-date=2020-10-07|doi-access=free }}</ref> In ALGOL-W, an integer expression was evaluated, which then evaluated the desired expression from a list of expressions:
<syntaxhighlight lang="pascal">
  J := case I of (3.14, 2.78, 448.9);
  A := case DECODE(C)-128 of ("A", "B", "C", "D", "E", "F");
</syntaxhighlight>

Other languages supporting the case expression include [SQL](/source/SQL), [Standard ML](/source/Standard_ML), [Haskell](/source/Haskell), [Common LISP](/source/Common_LISP), and [Oxygene](/source/Oxygene_(programming_language)).

===Switch expression===
The ''switch expression'' (introduced in [Java SE 12](/source/Java_version_history)) evaluates to a value. There is also a new form of case label, {{code|case L->}} where the right-hand-side is a single expression. This also prevents fall through and requires that cases are exhaustive. In Java SE 13 the <code>yield</code> statement is introduced, and in Java SE 14 switch expressions become a standard language feature.<ref>{{cite web|access-date=2021-04-28|title=JEP 325: Switch Expressions (Preview)|url=https://openjdk.java.net/jeps/325|website=openjdk.java.net}}</ref><ref>{{cite web|access-date=2021-04-28|title=JEP 354: Switch Expressions (Second Preview)|url=https://openjdk.java.net/jeps/354|website=openjdk.java.net}}</ref><ref>{{cite web|access-date=2021-04-28|title=JEP 361: Switch Expressions|url=https://openjdk.java.net/jeps/361|website=openjdk.java.net}}</ref> For example:  
<syntaxhighlight lang="java">
int dayCount = switch (month) {
    case JAN, MAR, MAY, JUL, AUG, OCT, DEC -> 31;
    case APR, JUN, SEP, NOV -> 30;
    case FEB -> {
        if (year % 400 == 0) {
            yield 29;
        } else if (year % 100 == 0) {
            yield 28;
        } else if (year % 4 == 0) {
            yield 29;
        } else {
            yield 28;
        }
    }
};
</syntaxhighlight>

Ruby also supports these semantics. For example:

<syntaxhighlight lang="ruby">
catfood =
  case
  when cat.age <= 1
    junior
  when cat.age > 10
    senior
  else
    normal
  end</syntaxhighlight>

==Exception handling==
A number of languages implement a form of switch statement in [exception handling](/source/exception_handling), where if an exception is raised in a block, a separate branch is chosen, depending on the exception. In some cases a default branch, if no exception is raised, is also present. An early example is [Modula-3](/source/Modula-3), which use the <code>TRY</code>...<code>EXCEPT</code> syntax, where each <code>EXCEPT</code> defines a case. This is also found in [Delphi](/source/Delphi_(programming_language)), [Scala](/source/Scala_(programming_language)), and [Visual Basic .NET](/source/Visual_Basic_.NET).

==Examples==

===C===
The following code is a switch statement in C. If {{code|age}} is 1, it outputs "You're one.". If {{code|age}} is 3, it outputs "You're three. You're three or four.". Switch statements in [C++](/source/C%2B%2B) behave the same as in C.

<syntaxhighlight lang="c">
#include <stdio.h>

void printAge(unsigned int age) {
    switch (age) {
        case 0:
            printf("You're newborn!");
            break;
        case 1:
            printf("You're one.");
            break;
        case 2:
            printf("You're two.");
            break;
        case 3:
            printf("You're three.");
        case 4:
            printf("You're three or four.");
            break;
        default:
            printf("You're older than 4 years old!");
    }
}
</syntaxhighlight>

Beginning in [C2Y](/source/C2Y), switch statements support specifying a range of cases to catch. This feature first appeared as a [GCC](/source/GNU_Compiler_Collection) extension for C.
<syntaxhighlight lang="c">
#include <stddef.h>
#include <stdio.h>
#include <uchar.h>

void writeUnicode(char32_t c) {
    switch (c) {
        // matches any value between [0, 0x7F] inclusive
        case 0 ... 0x7F: 
            putchar(c); 
            break;
        // matches any value between [0x80, 0x7FF] inclusive
        case 0x80 ... 0x7FF: 
            putchar(0xC0 + c >> 6);
            putchar(0x80 + c & 0x3f);
            break;
        // matches any value between [0x800, 0xFFFF] inclusive
        case 0x800 ... 0xFFFF:
            putchar(0xE0 + c >> 12);
            putchar(0x80 + (c >> 6) & 0x3f);
            putchar(0x80 + (c >> 12));
            break;
        default: 
            unreachable();
    }
}
</syntaxhighlight>

===Python===
Python (starting with 3.10.6) supports the {{code|match}} and {{code|case}} keywords.<ref>{{Cite web |last=Galindo Salgado |first=Pablo |title=What's New In Python 3.10 |url=https://docs.python.org/3/whatsnew/3.10.html |access-date=2022-08-19 |website=Python 3.10.6 documentation}}</ref><ref>{{Cite web |last1=Bucher |first1=Brandt |last2=van Rossum |first2=Guido |author-link2=Guido van Rossum |date=2020-09-12 |title=PEP 634 – Structural Pattern Matching: Specification |url=https://peps.python.org/pep-0634/ |access-date=2022-08-19 |website=Python Enhancement Proposals}}</ref><ref>{{Cite web |last1=Kohn |first1=Tobias |author-link=Guido van Rossum |last2=van Rossum |first2=Guido |date=2020-09-12 |title=PEP 635 – Structural Pattern Matching: Motivation and Rationale |url=https://peps.python.org/pep-0635/ |access-date=2022-08-19 |website=Python Enhancement Proposals}}</ref><ref>{{Cite web |last=Moisset |first=Daniel F |title=PEP 636 – Structural Pattern Matching: Tutorial |url=https://peps.python.org/pep-0636/ |access-date=2022-08-19 |website=Python Enhancement Proposals}}</ref> It doesn't allow fall through. Unlike if statement conditions, the {{code|or}} keyword cannot be used to differentiate between cases. {{code|case _}} is equivalent to {{code|default}} in C.

<syntaxhighlight lang="python">
letter: str = input("Enter a letter: ").strip()[0].casefold()
match letter:
    case "a" | "e" | "i" | "o" | "u":
        print(f"Letter '{letter}' is a vowel!")
    case "y":
        print(f"Letter '{letter}' may be a vowel.")
    case _:
        print(f"Letter '{letter}' is not a vowel!")
</syntaxhighlight>

===Pascal===
The following is an example in [Pascal](/source/Pascal_(programming_language)):

<syntaxhighlight lang="pascal">
case someChar of
  'a': actionOnA;
  'x': actionOnX;
  'y','z':actionOnYandZ;
  else actionOnNoMatch;
end;
</syntaxhighlight>

In the [Oxygene](/source/RemObjects_Elements) dialect of Pascal, a switch statement can be used as an expression:
<syntaxhighlight lang="pascal">
var i : Integer := case someChar of
  'a': 10;
  'x': 20;
  'y': 30;
  else -1;
end;
</syntaxhighlight>

===Shell script===
The following is an example in [Shell script](/source/Shell_script):

<syntaxhighlight lang="bash">
case $someChar in 
   a)    actionOnA; ;;
   x)    actionOnX; ;;
   [yz]) actionOnYandZ; ;;
  *)     actionOnNoMatch  ;;
esac
</syntaxhighlight>

===Assembler===
A switch statement in [assembly language](/source/assembly_language):
<syntaxhighlight lang="nasm">
switch:
  cmp ah, 00h
  je a
  cmp ah, 01h
  je b
  jmp swtend   ; No cases match or "default" code here
a:
  push ah
  mov al, 'a'
  mov ah, 0Eh
  mov bh, 00h
  int 10h
  pop ah
  jmp swtend   ; Equivalent to "break"
b:
  push ah
  mov al, 'b'
  mov ah, 0Eh
  mov bh, 00h
  int 10h
  pop ah
  jmp swtend   ; Equivalent to "break"
  ...
swtend:
</syntaxhighlight>

==Alternatives==
Some alternatives to using a switch statement include:

; if-then-else: A series of if-then-else [conditionals](/source/Conditional_(programming)) can test for each case value; one at a time. Fall through can be achieved with a sequence of if conditionals each without the else clause.

; Control table: The logic of a switch statement can be encoded as a [control table](/source/control_table) (a form of [lookup table](/source/lookup_table)) that is keyed by the case values and each value encodes what is otherwise in the case section {{endash}} as a [function pointer](/source/function_pointer) or [anonymous function](/source/anonymous_function) or similar mechanism.

:In a language that does not provide a switch statement, such as [Lua](/source/Lua),<ref name="lua">[http://lua-users.org/wiki/SwitchStatement Switch statement in Lua]</ref> a control table provides a way to implement switch statement semantics while enabling runtime efficiency that if-then-else does not.

; Pattern matching: [Pattern matching](/source/Pattern_matching) is switch-like functionality used in many [functional programming](/source/functional_programming) languages.

==History==
In his 1952 text ''Introduction to Metamathematics'', [Stephen Kleene](/source/Stephen_Kleene) formally proves that the case function (the if-then-else function being its simplest form) is a [primitive recursive function](/source/primitive_recursive_function), where he defines the notion "definition by cases" in the following manner:

{{blockquote|text=
"#F. The function φ defined thus
:  φ(x<sub>1</sub> , ... , x<sub>n</sub> ) =
::*φ<sub>1</sub>(x<sub>1</sub> , ... , x<sub>n</sub> ) if Q<sub>1</sub>(x<sub>1</sub> , ... , x<sub>n</sub> ),
::* .  .  .  .  .  .  .  .  .  .  .  .
::*φ<sub>m</sub>(x<sub>1</sub> , ... , x<sub>n</sub> ) if Q<sub>m</sub>(x<sub>1</sub> , ... , x<sub>n</sub> ),
::*φ<sub>m+1</sub>(x<sub>1</sub> , ... , x<sub>n</sub> ) otherwise,

where Q<sub>1</sub> , ... , Q<sub>m</sub> are mutually exclusive predicates (or φ(x<sub>1</sub> , ... , x<sub>n</sub>) shall have the value given by the first clause which applies) is primitive recursive in φ<sub>1</sub>, ..., φ<sub>m+1</sub>, Q<sub>1</sub>, ..., Q<sub>m+1</sub>.|author=Stephen Kleene|source=<ref>"Definition by cases", Kleene 1952:229</ref>}}

Kleene provides a proof of this in terms of the Boolean-like recursive functions "sign-of" sg( ) and "not sign of" ~sg( ) (Kleene 1952:222-223); the first returns 1 if its input is positive and −1 if its input is negative.

Boolos-Burgess-Jeffrey make the additional observation that "definition by cases" must be both [mutually exclusive](/source/mutually_exclusive) and [collectively exhaustive](/source/collectively_exhaustive). They too offer a proof of the primitive recursiveness of this function (Boolos-Burgess-Jeffrey 2002:74-75).

The if-then-else is the basis of the [McCarthy formalism](/source/McCarthy_formalism): its usage replaces both primitive recursion and the [mu-operator](/source/mu-operator).

The earliest [Fortran](/source/Fortran) compilers supported the [computed goto](/source/computed_goto) statement for multi-way branching. Early [ALGOL](/source/ALGOL) compilers supported a SWITCH data type which contains a list of "designational expressions". A goto statement could reference a switch variable and, by providing an index, branch to the desired destination. With experience it was realized that a more formal multi-way construct, with single point of entrance and exit, was needed. Languages such as [BCPL](/source/BCPL), [ALGOL-W](/source/ALGOL-W), and [ALGOL-68](/source/ALGOL-68) introduced forms of this construct which have survived through modern languages.

==See also==
* {{Annotated link |Algorithmic efficiency}}
* {{Annotated link |Index mapping}}

==References==
{{reflist}}

==Further reading==
* [Stephen Kleene](/source/Stephen_Kleene), 1952 (10th reprint 1991), ''Introduction to Metamathematics'', North-Holland Publishing Company, Amsterdam NL, {{ISBN|0-7204-2103-9}}
* [George Boolos](/source/George_Boolos), [John Burgess](/source/John_P._Burgess), and [Richard Jeffrey](/source/Richard_Jeffrey), 2002, ''Computability and Logic: Fourth Edition'', Cambridge University Press, Cambridge UK, {{ISBN|0-521-00758-5}} paperback. cf page 74–75.

Category:Conditional constructs

[ru:Оператор ветвления#Переключатель (оператор множественного выбора)](/source/ru%3A%D0%9E%D0%BF%D0%B5%D1%80%D0%B0%D1%82%D0%BE%D1%80_%D0%B2%D0%B5%D1%82%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F)

---
Adapted from the Wikipedia article [Switch statement](https://en.wikipedia.org/wiki/Switch_statement) by Wikipedia contributors ([contributor history](https://en.wikipedia.org/wiki/Switch_statement?action=history)). Available under [Creative Commons Attribution-ShareAlike 4.0 International](https://creativecommons.org/licenses/by-sa/4.0/). Changes may have been made.
