switch-Anweisung
Ü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:
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
|
(bis C++11) |
|
(seit C++11) |
- Der Deklarator darf keine Funktion oder ein Array angeben.
- Die Typ-Spezifizierer-Sequenz(bis C++11)Deklarations-Spezifizierer-Sequenz darf nur Typ-Spezifizierer und constexpr enthalten, und sie(seit C++11) darf keine Klasse oder Aufzählung definieren.
Die Entscheidungsvariable der Deklaration ist die deklarierte Variable.
Strukturierte BindungsdeklarationDie 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-Anweisungen mit InitialisiererWenn init-statement verwendet wird, ist die switch-Anweisung äquivalent zu
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.
[bearbeiten] Schlüsselwörter
[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. |