Namespaces
Variants
Actions

switch statement

From cppreference.com
< cpp‎ | language
 
 
C++ language
General topics
Flow control
Conditional execution statements
switch
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications(until C++17*)
noexcept specifier(C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr(C++11)
consteval(C++20)
constinit(C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr(C++11)
User-defined(C++11)
Utilities
Attributes(C++11)
Types
typedef declaration
Type alias declaration(C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous
 
 

Transfers control to one of several statements, depending on the value of a condition.

Contents

[edit]Syntax

attr (optional)switch(init-statement (optional)condition)statement
attr - (since C++11) any number of attributes
init-statement - (since C++17) any of the following:
(since C++23)

Note that any init-statement must end with a semicolon. This is why it is often described informally as an expression or a declaration followed by a semicolon.

condition - a condition
statement - a statement (typically a compound statement)

[edit]Condition

A condition can either be an expression or a simple declaration.

  • If it can be syntactically resolved as a structured binding declaration, it is interpreted as a structured binding declaration.
(since C++26)
  • If it can be syntactically resolved as an expression, it is treated as an expression. Otherwise, it is treated as a declaration that is not a structured binding declaration(since C++26).

When control reaches condition, the condition will yield a value, which is used to determine which label the control will go to.

[edit]Expression

If condition is an expression, the value it yields is the the value of the expression.

[edit]Declaration

If condition is a simple declaration, the value it yields is the value of the decision variable (see below).

[edit]Non-structured binding declaration

The declaration has the following restrictions:

  • Syntactically conforms to the following form:
  • type-specifier-seqdeclarator=assignment-expression
(until C++11)
  • attribute-specifier-seq(optional)decl-specifier-seqdeclaratorbrace-or-equal-initializer
(since C++11)

The decision variable of the declaration is the declared variable.

Structured binding declaration

The declaration has the following restrictions:

The decision variable of the declaration is the invented variable eintroduced by the declaration.

(since C++26)

[edit]Type

condition can only yield the following types:

  • integral types
  • enumeration types
  • class types

If the yielded value is of a class type, it is contextually implicitly converted to an integral or enumeration type.

If the (possibly converted) type is subject to integral promotions , the yielded value is converted to the promoted type.

[edit]Labels

Any statement within the switch statement can be labeled with one or more following labels:

attr (optional)caseconstant-expression: (1)
attr (optional)default: (2)
attr - (since C++11) any number of attributes
constant-expression - a converted constant expression of the adjusted type of the switch condition


A case or default label is associated with the innermost switch statement enclosing it.

If any of the following conditions is satisfied, the program is ill-formed:

  • A switch statement is associated with multiple case labels whose constant-expression s have the same value after conversions.
  • A switch statement is associated with multiple default labels.

[edit]Control flow transfer

When the condition of a switch statement yields a (possibly converted) value:

  • If one of the associated case label constants has the same value, control is passed to the statement labeled by the matched case label.
  • Otherwise, if there is an associated default label, control is passed to the statement labeled by the default label.
  • Otherwise, none of the statements in the switch statement will be executed.

case and default labels in themselves do not alter the flow of control. To exit from a switch statement from the middle, see break statements.

Compilers may issue warnings on fallthrough (reaching the next case or default label without a break) unless the attribute [[fallthrough]] appears immediately before the case label to indicate that the fallthrough is intentional(since C++17).

switch(1){case1:std::cout<<'1';// prints "1",case2:std::cout<<'2';// then prints "2"}
switch(1){case1:std::cout<<'1';// prints "1"break;// and exits the switchcase2:std::cout<<'2';break;}

switch statements with initializer

If init-statement is used, the switch statement is equivalent to

{
init-statement
switch(condition)statement

}

Except that names declared by the init-statement (if init-statement is a declaration) and names declared by condition (if condition is a declaration) are in the same scope, which is also the scope of statement.

(since C++17)

[edit]Notes

Because transfer of control is not permitted to enter the scope of a variable, if a declaration statement is encountered inside the statement, it has to be scoped in its own compound statement:

switch(1){case1:int x =0;// initializationstd::cout<< x <<'\n';break;default:// compilation error: jump to default:// would enter the scope of 'x' without initializing itstd::cout<<"default\n";break;}
switch(1){case1:{int x =0;std::cout<< x <<'\n';break;}// scope of 'x' ends heredefault:std::cout<<"default\n";// no errorbreak;}

[edit]Keywords

switch, case, default

[edit]Example

The following code shows several usage cases of the switch statement:

#include <iostream>   int main(){constint i =2;switch(i){case1:std::cout<<'1';case2:// execution starts at this case labelstd::cout<<'2';case3:std::cout<<'3';[[fallthrough]];// C++17 attribute to silent the warning on fallthroughcase5:std::cout<<"45";break;// execution of subsequent statements is terminatedcase6:std::cout<<'6';}   std::cout<<'\n';   switch(i){case4:std::cout<<'a';default:std::cout<<'d';// there are no applicable constant expressions // therefore default is executed}   std::cout<<'\n';   switch(i){case4:std::cout<<'a';// nothing is executed}   // when enumerations are used in a switch statement, many compilers// issue warnings if one of the enumerators is not handledenum color { RED, GREEN, BLUE };switch(RED){case RED:std::cout<<"red\n";break;case GREEN:std::cout<<"green\n";break;case BLUE:std::cout<<"blue\n";break;}   // the C++17 init-statement syntax can be helpful when there is// no implicit conversion to integral or enumeration typestruct Device {enum State { SLEEP, READY, BAD };auto state()const{return m_state;}   /* ... */   private: State m_state{};};   switch(auto dev = Device{}; dev.state()){case Device::SLEEP:/* ... */break;case Device::READY:/* ... */break;case Device::BAD:/* ... */break;}   // pathological examples   // the statement does not have to be a compound statementswitch(0)std::cout<<"this does nothing\n";   // labels do not require a compound statement eitherswitch(int n =1)case0:case1:std::cout<< n <<'\n';}

Output:

2345 d red 1

[edit]Defect reports

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

DR Applied to Behavior as published Correct behavior
CWG 1767C++98 condition s of types that are not subject to
integral promotion could not be promoted
do not promote
condition s of these types
CWG 2629C++98 condition could be a declaration of a floating-point variable prohibited

[edit]See also

C documentation for switch

[edit]External links

1. Loop unrolling using Duff's Device
2. Duff's device can be used to implement coroutines in C/C++
close