Ich schrieb diese Antwort ursprünglich für diese Frage . Als ich sie jedoch fertiggestellt hatte, stellte ich fest, dass die Antwort bereits geschlossen wurde. Also habe ich sie hier gepostet, vielleicht findet sie jemand, der sich gerne auf Standards bezieht, hilfreich.
Der betreffende Originalcode:
int i;
i = 2;
switch(i)
{
case 1:
int k;
break;
case 2:
k = 1;
cout<<k<<endl;
break;
}
Es gibt eigentlich 2 Fragen:
1. Warum kann ich eine Variable deklarieren nach case
Etikett?
Das liegt daran, dass in C++ das Etikett in Form sein muss:
N3337 6.1/1
beschriftete Aussage:
...
- attribut-specifier-seqopt
case
constant-expression
: statement
...
Und in C++
Deklarationserklärung wird auch betrachtet als Anweisung (im Gegensatz zu C
):
N3337 6/1:
Anweisung :
...
Deklaration-Aussage
...
2. Warum kann ich eine Variablendeklaration überspringen und sie dann verwenden?
Weil: N3337 6.7/3
Es ist möglich, in einen Block zu wechseln, aber nicht so, dass Deklarationen mit Initialisierung umgangen werden . A Programm, das springt (Die Übertragung von den Zustand eines switch-Anweisung an ein Case-Label wird als Sprung betrachtet in dieser Hinsicht).
von einem Punkt, an dem eine Variable mit automatischer Speicherdauer nicht in den Anwendungsbereich fällt, zu einem Punkt, an dem sie in den Anwendungsbereich fällt, ist schlecht geformt es sei denn, die Variable ist skalarer Art Klassenart mit trivialem Standard Konstruktor und einem trivialen Destruktor, eine cv-qualifizierte Version eines dieser Typen oder ein Array von einem der Typs und wird ohne Initialisierer deklariert (8.5).
Desde k
ist von Skalartyp und zum Zeitpunkt der Deklaration nicht initialisiert ist, ist ein Überspringen der Deklaration möglich. Dies ist semantisch äquivalent:
goto label;
int x;
label:
cout << x << endl;
Das wäre jedoch nicht möglich, wenn x
wurde zum Zeitpunkt der Deklaration initialisiert:
goto label;
int x = 58; //error, jumping over declaration with initialization
label:
cout << x << endl;