Namensräume
Varianten
Aktionen

switch-Anweisung

Von cppreference.com
< cpp‎ | Sprache
 
 
C++ Sprache
Allgemeine Themen
Kontrollfluss
Bedingte Ausführungsaussagen
if
switch
Iterationsanweisungen (Schleifen)
for
Bereichs-for (C++11)
Sprunganweisungen
Funktionen
Funktionsdeklaration
Lambda-Funktionsausdruck
inline-Spezifizierer
Dynamische Ausnahmespezifikationen (bis C++17*)
noexcept-Spezifizierer (C++11)
Ausnahmen
Namensräume
Typen
Spezifizierer
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Speicherdauer-Spezifizierer
Initialisierung
Ausdrücke
Alternative Darstellungen
Literale
Boolesch - Ganzzahl - Gleitkommazahl
Zeichen - String - nullptr (C++11)
Benutzerdefinierte (C++11)
Dienstprogramme
Attribute (C++11)
Typen
typedef-Deklaration
Typalias-Deklaration (C++11)
Umwandlungen
Speicherzuweisung
Klassen
Klassenspezifische Funktionseigenschaften
explicit (C++11)
static

Spezielle Member-Funktionen
Templates
Sonstiges
 
 

Überträgt die Kontrolle basierend auf dem Wert einer Bedingung zu einer von mehreren Anweisungen.

Inhalt

[bearbeiten] Syntax

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

Beachten Sie, dass jede init-statement mit einem Semikolon enden muss. Deshalb wird sie oft informell als Ausdruck oder Deklaration gefolgt von einem Semikolon beschrieben.

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

[bearbeiten] Bedingung

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

(seit C++26)
  • Wenn sie syntaktisch als Ausdruck aufgelöst werden kann, wird sie als Ausdruck behandelt. Andernfalls wird sie als Deklaration behandelt, die keine strukturierte Bindungsdeklaration ist(seit C++26).

Wenn die Kontrolle auf die Bedingung trifft, liefert die Bedingung einen Wert, der verwendet wird, um zu bestimmen, zu welchem Label die Kontrolle übergeht.

[bearbeiten] Ausdruck

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

[bearbeiten] Deklaration

Wenn condition eine einfache Deklaration ist, ist der von ihm gelieferte Wert der Wert der Entscheidungs variable (siehe unten).

[bearbeiten] Nicht-strukturierte Bindungsdeklaration

Die Deklaration hat folgende Einschränkungen

  • Folgt syntaktisch 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 hat folgende Einschränkungen

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

(seit C++26)

[bearbeiten] Typ

condition kann nur die folgenden Typen liefern:

  • ganzzahlige Typen
  • Aufzählungstypen
  • Klassentypen

Wenn der gelieferte Wert vom Typ einer Klasse ist, wird er kontextbezogen implizit in einen ganzzahligen Typ oder einen Aufzählungstyp umgewandelt.

Wenn der (möglicherweise umgewandelte) Typ ganzzahligen Promotionen unterliegt, wird der gelieferte Wert in den beförderten Typ konvertiert.

[bearbeiten] Labels

Jede Anweisung innerhalb der switch-Anweisung kann mit einem oder mehreren folgenden Labels versehen werden:

attr (optional) case constant-expression : (1)
attr (optional) default: (2)
attr - (seit C++11) eine beliebige Anzahl von Attributen
konstanter Ausdruck - ein konvertierter konstanter Ausdruck vom angepassten Typ der switch-Bedingung


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

Wenn eine der folgenden Bedingungen erfüllt ist, ist das Programm ill-formed (wohlgeformt):

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

[bearbeiten] Kontrollflussübertragung

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

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

case- und default-Labels ändern für sich genommen nicht den Kontrollfluss. Um eine switch-Anweisung von innen zu verlassen, siehe break-Anweisungen.

Compiler können Warnungen bei "Fallthrough" (Erreichen des nächsten case- oder default-Labels ohne 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'; // 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-Anweisungen mit Initialisierer

Wenn init-statement verwendet wird, ist die switch-Anweisung äquivalent zu

{
init-statement
switch ( condition ) statement

}

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

(seit C++17)

[bearbeiten] Hinweise

Da die Übertragung der Kontrolle nicht erlaubt ist, um den Gültigkeitsbereich einer Variablen zu betreten, muss, wenn eine Deklarationsanweisung innerhalb von statement angetroffen wird, diese in ihrer eigenen zusammengesetzten Anweisung eingeschlossen sein.

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;
}

[bearbeiten] Schlüsselwörter

switch, case, default

[bearbeiten] 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:              // 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';
}

Ausgabe

2345
d
red
1

[bearbeiten] Fehlerberichte

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

DR angewendet auf Verhalten wie veröffentlicht Korrigiertes Verhalten
CWG 1767 C++98 condition s von Typen, die nicht
ganzzahligen Promotionen unterliegen, konnten nicht befördert werden
werden nicht befördert
condition s dieser Typen
CWG 2629 C++98 condition konnte eine Deklaration einer Fließkomma-Variable sein verboten

[bearbeiten] Siehe auch

C-Dokumentation für switch

[bearbeiten] Externe Links

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