2016-08-06 9 views
4

Betrachten Sie dieses C-Code, wo foo ist ein int:Erklärungen in switch-Anweisung

switch(foo){ 
    case 1: { 
     int bla = 255; 
     case 2: 
      printf("case12 %d\n", bla); 
     break; 
     case 3: 
      printf("case3 %d\n", bla); 
    } 
}; 

Für verschiedene Werte von foo der Code die folgende Ausgabe gibt:

case12 255 # foo=1 
case12 255 # foo=2 
case3 0  # foo=3 

Ich habe ein Problem Verständnis . Die Zeile, die bla deklariert und ihren Wert definiert, sollte nicht ausgeführt werden, wenn . Die switch-Anweisung sollte direkt auf das Label für case 3: springen. Aber es gibt keine Warnung, also scheint bla mindestens deklariert worden zu sein. Es könnte uninitialisiert verwendet werden und sein Wert ist nur zufällig 0, obwohl. Kannst du erklären, was in "Fall 3" passiert und warum dies legaler C-Code ist?

+2

Sie don‘ t brauche das Semikolon nach dem letzten '}'. –

+0

Seltsamerweise akzeptiert GCC den Code im C-Modus (mit einer Warnung), lehnt ihn jedoch im C++ - Modus ab. – HolyBlackCat

+0

Nicht so seltsam: http://stackoverflow.com/questions/92396/why-cant-variables-be-declared-in-a-switch-statement?rq=1 – melpomene

Antwort

7

Eine switch Anweisung ist im Wesentlichen eine berechnete goto. Die case Beschriftungen können innerhalb der (normalerweise zusammengesetzten) Anweisung, die von switch gesteuert wird, auch innerhalb verschachtelter Blöcke angezeigt werden.

Die Erklärung int bla = 255; erzeugt ein Objekt intbla deren Lebensdauer ist die Ausführung des einschließenden Blocks und dessen Name von dem Punkt seiner Deklaration bis zum Ende des Blocks sichtbar ist.

Wenn die switch Anweisung Ursachen der case 2: oder case 3: Label zu springen steuern, springt er in den Anwendungsbereich der bla aber springt Vergangenheit seiner Initialisierung. Der Wert von bla ist dann Müll (nicht zufällig, nicht notwendigerweise 0) und in der Tat versucht, auf seinen Wert zu verweisen hat undefiniertes Verhalten.

Sie können mit einer goto Anweisung

Tu das nicht das gleiche tun.

(für gcc, erhalten Sie eine Warnung erhalten, wenn Sie mit -Wall kompilieren oder -Wextra oder -Wmaybe-uninitialized.)

(Für einen weiteren Missbrauch der switch-Anweisung finden Sie Duff's Device.)

+0

Danke für die Antwort. Ich verstehe immer noch nicht, warum das 'bla' überhaupt existiert. Naiverweise würde ich annehmen, dass die Deklaration ebenfalls übersprungen wird (nicht nur die Initialisierung). Aber offensichtlich bietet der Code 'bla'. –

+2

@ con-f-use: Es existiert, weil die Steuerung den Block eingegeben hat, in dem sie definiert ist. Seine * Lebensdauer * beginnt, wenn die Steuerung die Öffnung '{' erreicht und überspringt und endet, wenn die Steuerung das schließende '}' erreicht. Die Initialisierung findet erst statt, wenn die Steuerung die Deklaration erreicht - und überhaupt nicht, wenn die Deklaration übersprungen wird. (C++ verbietet diese Art von Sprung.) –

+0

@ con-f-use: Wenn die Definition von 'bla' übersprungen würde, könnte der Code nicht kompiliert werden. Wie es kompiliert, beweist dies, dass "bla" definiert ist. – alk

Verwandte Themen