Namespaces
Variants

switch statement

From cppreference.net
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

Überträgt die Steuerung an eine von mehreren Anweisungen, abhängig vom Wert einer Bedingung.

Inhaltsverzeichnis

Syntax

attr  (optional) switch ( init-statement  (optional) condition ) statement
attr - (since C++11) beliebige Anzahl von Attributen
init-statement - (since C++17) eines der folgenden Elemente:
(since C++23)

Beachten Sie, dass jede init-statement mit einem Semikolon enden muss. Dies ist der Grund, warum sie informell oft als ein Ausdruck oder eine Deklaration gefolgt von einem Semikolon beschrieben wird.

condition - eine Bedingung
statement - eine Anweisung (typischerweise eine zusammengesetzte Anweisung)

Bedingung

Eine Bedingung kann entweder ein Ausdruck oder eine einfache Deklaration sein.

  • Wenn es syntaktisch als eine structured binding -Deklaration aufgelöst werden kann, wird es als eine structured binding-Deklaration interpretiert.
(seit C++26)
  • Wenn es syntaktisch als Ausdruck aufgelöst werden kann, wird es als Ausdruck behandelt. Andernfalls wird es als Deklaration behandelt die keine strukturierte Bindungsdeklaration ist (seit C++26) .

Wenn die Steuerung die Bedingung erreicht, ergibt die Bedingung einen Wert, der verwendet wird, um zu bestimmen, zu welchem Label die Steuerung gehen wird.

Ausdruck

Wenn condition ein Ausdruck ist, ist der von ihm gelieferte Wert der Wert des Ausdrucks.

Deklaration

Wenn condition eine einfache Deklaration ist, ist der von ihr gelieferte Wert der Wert der Entscheidungsvariablen (siehe unten).

Nicht-strukturierte Bindungsdeklaration

Die Deklaration unterliegt folgenden Einschränkungen:

  • Syntaktisch entspricht es der folgenden Form:
  • type-specifier-seq declarator = assignment-expression
(bis C++11)
  • attribute-specifier-seq (optional) decl-specifier-seq declarator brace-or-equal-initializer
(seit C++11)

Die Entscheidungsvariable der Deklaration ist die deklarierte Variable.

Strukturierte Bindungsdeklaration

Die Deklaration unterliegt folgenden Einschränkungen:

Die Entscheidungsvariable der Deklaration ist die eingeführte Variable e , die durch die Deklaration eingeführt wird .

(seit C++26)

Typ

condition kann nur die folgenden Typen ergeben:

  • Ganzzahlige Typen
  • Aufzählungstypen
  • Klassentypen

Wenn der gelieferte Wert von einem Klassentyp ist, wird er kontextuell implizit in einen integralen oder Aufzählungstyp konvertiert.

Wenn der (möglicherweise konvertierte) Typ integral promotions unterliegt, wird der resultierende Wert in den höherwertigen Typ konvertiert.

Labels

Jede Anweisung innerhalb der switch -Anweisung kann mit einer oder mehreren der folgenden Bezeichnungen versehen werden:

attr  (optional) case constant-expression : (1)
attr  (optional) default: (2)
attr - (seit C++11) beliebig viele Attribute
constant-expression - ein konvertierter konstanter Ausdruck des angepassten Typs der switch -Bedingung


Ein case - oder default -Label ist mit der innersten switch -Anweisung verknüpft, die es umschließt.

Wenn eine der folgenden Bedingungen erfüllt ist, ist das Programm fehlerhaft:

  • Eine switch -Anweisung ist mit mehreren case -Labels verknüpft, deren constant-expression s nach Konvertierungen denselben Wert haben.
  • Eine switch -Anweisung ist mit mehreren default -Labels verknüpft.

Kontrollflussübertragung

Wenn die Bedingung einer switch -Anweisung einen (möglicherweise konvertierten) Wert ergibt:

  • Wenn eine der zugehörigen case Label-Konstanten denselben Wert hat, wird die Steuerung an die Anweisung übergeben, die durch das übereinstimmende case Label gekennzeichnet ist.
  • Andernfalls, wenn ein zugehöriges default Label vorhanden ist, wird die Steuerung an die Anweisung übergeben, die durch das default Label gekennzeichnet ist.
  • Andernfalls wird keine der Anweisungen in der switch Anweisung ausgeführt.

case und default Labels an sich verändern den Kontrollfluss nicht. Um eine switch -Anweisung in der Mitte zu verlassen, siehe break -Anweisungen .

Compiler können Warnungen zu Fallthrough (Erreichen des nächsten case - oder default -Labels ohne einen break ) ausgeben, es sei denn, das Attribut [[ fallthrough ]] erscheint unmittelbar vor dem case -Label, um anzuzeigen, dass der Fallthrough beabsichtigt ist (seit C++17) .

switch (1)
{
    case 1:
        std::cout << '1'; // gibt "1" aus,
    case 2:
        std::cout << '2'; // dann gibt "2" aus
}
switch (1)
{
    case 1:
        std::cout << '1'; // gibt "1" aus
        break;            // und beendet den switch
    case 2:
        std::cout << '2';
        break;
}

switch Anweisungen mit Initialisierer

Falls init-statement verwendet wird, entspricht die switch-Anweisung:

{
init-statement
switch ( condition ) statement

}

Mit der Ausnahme, dass Namen, die durch den init-statement deklariert werden (falls init-statement eine Deklaration ist) und Namen, die durch condition deklariert werden (falls condition eine Deklaration ist), sich im selben Gültigkeitsbereich befinden, welcher auch der Gültigkeitsbereich von statement ist.

(seit C++17)

Hinweise

Da die Übertragung der Kontrolle nicht erlaubt ist, in den Geltungsbereich einer Variable einzutreten, muss eine Deklarationsanweisung, die innerhalb der Anweisung angetroffen wird, in ihrer eigenen zusammengesetzten Anweisung geschachtelt werden:

switch (1)
{
    case 1:
        int x = 0; // Initialisierung
        std::cout << x << '\n';
        break;
    default:
        // Kompilierungsfehler: Sprung zu default:
        // würde den Gültigkeitsbereich von 'x' betreten ohne es zu initialisieren
        std::cout << "default\n";
        break;
}
switch (1)
{
    case 1:
        {
            int x = 0;
            std::cout << x << '\n';
            break;
        } // Gültigkeitsbereich von 'x' endet hier
    default:
        std::cout << "default\n"; // kein Fehler
        break;
}

Schlüsselwörter

switch , case , default

Beispiel

Der folgende Code zeigt mehrere Anwendungsfälle der switch -Anweisung:

#include <iostream>
int main()
{
    const int i = 2;
    switch (i)
    {
        case 1:
            std::cout << '1';
        case 2:              // Ausführung beginnt bei diesem case-Label
            std::cout << '2';
        case 3:
            std::cout << '3';
            [[fallthrough]]; // C++17-Attribut zur Unterdrückung der Fallthrough-Warnung
        case 5:
            std::cout << "45";
            break;           // Ausführung nachfolgender Anweisungen wird beendet
        case 6:
            std::cout << '6';
    }
    std::cout << '\n';
    switch (i)
    {
        case 4:
            std::cout << 'a';
        default:
            std::cout << 'd'; // es gibt keine anwendbaren konstanten Ausdrücke
                              // daher wird default ausgeführt
    }
    std::cout << '\n';
    switch (i)
    {
        case 4:
            std::cout << 'a'; // nichts wird ausgeführt
    }
    // wenn Aufzählungen in einer switch-Anweisung verwendet werden, geben
    // viele Compiler Warnungen aus, wenn einer der Enumeratoren nicht behandelt wird
    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;
    }
    // die C++17 Init-Statement-Syntax kann hilfreich sein, wenn keine
    // implizite Konvertierung zu integralem oder Aufzählungstyp vorhanden ist
    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;
    }
    // pathologische Beispiele
    // die Anweisung muss kein zusammengesetzter Ausdruck sein
    switch (0)
        std::cout << "this does nothing\n";
    // Labels erfordern ebenfalls keinen zusammengesetzten Ausdruck
    switch (int n = 1)
        case 0:
        case 1:
            std::cout << n << '\n';
}

Ausgabe:

2345
d
red
1

Fehlerberichte

Die folgenden verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.

DR Angewendet auf Verhalten wie veröffentlicht Korrektes Verhalten
CWG 1767 C++98 condition s von Typen, die nicht für
integrale Promotion geeignet waren, konnten nicht gepromotet werden
keine Promotion von
condition s dieser Typen durchführen
CWG 2629 C++98 condition konnte eine Deklaration einer Gleitkommavariable sein verboten

Siehe auch

C-Dokumentation für switch

Externe Links

1. Schleifenabrollung mit Duff's Device
2. Duff's Device kann zur Implementierung von Coroutinen in C/C++ verwendet werden