switch statement - cppreference.com (original) (raw)

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: an expression statement (which may be a null statement ;) a simple declaration, typically a declaration of a variable with initializer, but it may declare arbitrarily many variables or structured bindings 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)

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:

type-specifier-seq declarator = assignment-expression (until C++11)
attribute-specifier-seq(optional) decl-specifier-seq declarator brace-or-equal-initializer (since C++11)

The decision variable of the declaration is the declared variable.

[edit] Type

condition can only yield the following 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) case constant-expression : | (1) | | | | | | | attr (optional) default: | (2) | | | | | |

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:

[edit] Control flow transfer

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

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](attributes/fallthrough.html "cpp/language/attributes/fallthrough")]] appears immediately before the case label to indicate that the fallthrough is intentional(since C++17).

switch (1) { case 1: std::cout << '1'; // prints "1", case 2: std::cout << '2'; // then prints "2" }

switch (1) { case 1: std::cout << '1'; // prints "1" break; // and exits the switch case 2: 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) { case 1: int x = 0; // initialization std::cout << x << '\n'; break; default: // compilation error: jump to default: // would enter the scope of 'x' without initializing it std::cout << "default\n"; break; }

switch (1) { case 1: { int x = 0; std::cout << x << '\n'; break; } // scope of 'x' ends here default: std::cout << "default\n"; // no error break; }

[edit] Keywords

switch,case,default

[edit] Example

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

#include   int main() { const int i = 2; switch (i) { case 1: std::cout << '1'; case 2: // execution starts at this case label std::cout << '2'; case 3: std::cout << '3'; [[fallthrough]]; // C++17 attribute to silent the warning on fallthrough case 5: std::cout << "45"; break; // execution of subsequent statements is terminated case 6: std::cout << '6'; }   std::cout << '\n';   switch (i) { case 4: std::cout << 'a'; default: std::cout << 'd'; // there are no applicable constant expressions // therefore default is executed }   std::cout << '\n';   switch (i) { case 4: 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 handled enum 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 type struct 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 statement switch (0) std::cout << "this does nothing\n";   // labels do not require a compound statement either switch (int n = 1) case 0: case 1: std::cout << n << '\n'; }

Output:

[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 1767 C++98 condition s of types that are not subject tointegral promotion could not be promoted do not promotecondition s of these types
CWG 2629 C++98 condition could be a declaration of a floating-point variable prohibited

[edit] See also