This article needs additional citations for verification .(April 2013) |
In computer programming, a switch statement is a selection control flow mechanism that changes execution control based on the value of an expression (i.e. evaluation of a variable). A switch statement is similar to an 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, most imperative languages provide a statement with the semantics described here as the switch statement. Often denoted with the keyword switch
, some languages use variations such as case
, select
, or inspect
.
Sometimes, use of a switch statement is considered superior to an equivalent series of if-then-else statements because it is:
Typically, a switch statement involves:
select
which is followed by an expression which is often a variable name; the control expression or control variable.case
) plus a value (or multiple values) along with code to execute for the value(s). In some languages, i.e. PL/I and Rexx, if the control expression is omitted then each alternative begins with a 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.break
) if that section should not fall through.default
, otherwise
, or 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.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-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 but supports branching on more than just true and false values. To allow multiple values to execute the same code (avoiding duplicate code), the syntax permits multiple values per case.
An unstructured switch, as in C (and more generally languages influenced by Fortran's computed GOTO), acts like 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. break
), but a common mistake is to accidentally omit the keyword; causing unintentional fall through and often a bug. Therefore, many consider this language feature to be dangerous, [3] and often fall through code results in a warning from a code quality tool such as lint.
Some languages, such as JavaScript, retain fall through semantics, while others exclude or restrict it. Notably, in C# all blocks must be terminated with break
or 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 does not fall through by default, but a case may explicitly do so using a continue
keyword; preventing unintentional fall through. Similarly, Bash defaults to not falling through when terminated with ;;
, but allows fall through [4] with ;&
or ;;&
instead.
An example of a switch statement that relies on fall through is Duff's device.
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 and Ruby, 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.
switch(true){case($x=='hello'):foo();break;case($z=='howdy'):break;}
This feature is also useful for checking multiple variables against one value rather than one variable against many values.
switch(5){case$x:break;case$y:break;}
COBOL also supports this form via its EVALUATE
statement. PL/I supports similar behavior by omitting the control expression, and the first WHEN
expression that evaluates as true is executed.
In Ruby, due to its handling of ===
equality, the case expression can be used to test a variable’s class. For example:
caseinputwhenArraythenputs'input is an Array!'whenHashthenputs'input is a Hash!'end
Some languages support evaluating a switch statement to a value.
The case expression is supported by languages dating at least as far back as ALGOL-W. [5] In ALGOL-W, an integer expression was evaluated, which then evaluated the desired expression from a list of expressions:
J:=caseIof(3.14,2.78,448.9);A:=caseDECODE(C)-128of("A","B","C","D","E","F");
Other languages supporting the case expression include SQL, Standard ML, Haskell, and Common LISP.
The switch expression (introduced in Java SE 12) evaluates to a value. There is also a new form of case label, 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 yield
statement is introduced, and in Java SE 14 switch expressions become a standard language feature. [6] [7] [8] For example:
intndays=switch(month){caseJAN,MAR,MAY,JUL,AUG,OCT,DEC->31;caseAPR,JUN,SEP,NOV->30;caseFEB->{if(year%400==0)yield29;elseif(year%100==0)yield28;elseif(year%4==0)yield29;elseyield28;}};
Ruby also supports these semantics. For example:
catfood=casewhencat.age<=1juniorwhencat.age>10seniorelsenormalend
A number of languages implement a form of switch statement in 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, which use the TRY
...EXCEPT
syntax, where each EXCEPT
defines a case. This is also found in Delphi, Scala, and Visual Basic .NET.
The following code is a switch statement in C. If age
is 1, it outputs "You're one.". If age
is 3, it outputs "You're three. You're three or four.".
switch(age){case1:printf("You're one.");break;case2:printf("You're two.");break;case3:printf("You're three.");case4:printf("You're three or four.");break;default:printf("You're not 1, 2, 3 or 4!");}
Python (starting with 3.10.6) supports the match
and case
keywords. [9] [10] [11] [12] It doesn't allow fall through. Unlike if statement conditions, the or
keyword cannot be used to differentiate between cases. case _
is equivalent to default
in C.
letter=input("Enter a letter: ").strip()[0].casefold()matchletter: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!")
A switch statement in assembly language:
switch:cmpah,00hjeacmpah,01hjebjmpswtend; No cases match or "default" code herea:pushahmoval,'a'movah,0Ehmovbh,00hint10hpopahjmpswtend; Equivalent to "break"b:pushahmoval,'b'movah,0Ehmovbh,00hint10hpopahjmpswtend; Equivalent to "break"...swtend:
Some alternatives to using a switch statement include:
In his 1952 text Introduction to Metamathematics, Stephen Kleene formally proves that the case function (the if-then-else function being its simplest form) is a primitive recursive function, where he defines the notion "definition by cases" in the following manner:
"#F. The function φ defined thus
- φ(x1 , ... , xn ) =
- φ1(x1 , ... , xn ) if Q1(x1 , ... , xn ),
- . . . . . . . . . . . .
- φm(x1 , ... , xn ) if Qm(x1 , ... , xn ),
- φm+1(x1 , ... , xn ) otherwise,
where Q1 , ... , Qm are mutually exclusive predicates (or φ(x1 , ... , xn) shall have the value given by the first clause which applies) is primitive recursive in φ1, ..., φm+1, Q1, ..., Qm+1.
— Stephen Kleene, [14]
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 and 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: its usage replaces both primitive recursion and the mu-operator.
The earliest Fortran compilers supported the computed GOTO statement for multi-way branching. Early 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, ALGOL-W, and ALGOL-68 introduced forms of this construct which have survived through modern languages.