2013-08-08 4 views
13

Heute habe ich zufällig entdeckt, dass mein Compiler nicht beim Schreiben von Code innerhalb einer Switch-Anweisung ohne einen Fall zu klagen. (Es beschwerte sich über das Fehlen von Case-Anweisungen, aber nach dem Hinzufügen eines nach dem Code, gab es nicht einmal eine Warnung, um mich wissen zu lassen, dass der Code nutzlos war.)Switch ohne Case

Ich versuche herauszufinden, ob Es gibt einen Zweck, den folgenden Code zuzulassen, oder wenn es nur eines dieser Dinge ist, bei denen "es mehr Arbeit ist, es einzuschränken, also ist es erlaubt".

#include <iostream> 
void foo() { 
    std::cout << "foo" << std::endl; 
} 

int main() 
{ 
    for (int a = -10; a < 10; ++a) 
    { 
     switch(a) 
     { 
     foo(); 
     case 4: 
     std::cout << "4" << std::endl; 
     } 
    } 
} 

Dies gibt nun "4" wie erwartet, wenn ein == 4, und es nie foo ausgibt. Die Frage ist also, gibt es einen (möglicherweise esoterischen, aber nützlichen) Grund, die Aussage foo(); vor dem ersten Fall zu berücksichtigen? Ich bin mir sicher, dass ich dort keine Variablen deklarieren und initialisieren darf.

(FWIW, habe ich dies auf mehrere Compiler getestet, und sie sind alle das gleiche Verhalten ergibt. Überraschenderweise sie alle Ausgaben auch nicht eine Warnung.)

+2

Welcher Compiler ist das? – turnt

+0

Ich habe dies sowohl auf MSVC 2012 und GCC 4.8.1 getestet. – Shirik

+0

Hmm interessant. Ein Gedanke, der mir in den Sinn kommt, ist, dass ich keinen Standard schreiben muss und stattdessen nur den Code unter dem letzten Fall schreibe. Aber, das schreit möglicherweise schlechte Praxis :) –

Antwort

8

Ja, das Verhalten wie vorgesehen in die Sprache und Sie können Code an verschiedenen Orten hinzufügen. Switch-Anweisungen sind viel komplizierter als das Aussehen, und sie erlauben ziemlich esoterischen Code, ob es Sinn macht oder nicht.

Wenn Sie einige Zeit verwenden möchten, um einige seltsame Anwendungen von switch und den Speicherort von Fällen zu betrachten, können Sie die Implementierung von Korotinen in der Boost Asio-Bibliothek betrachten. Sie können eine kleine Funktion mit den Makros schreiben, kompilieren und sehen, wie der generierte Code (nach der Makroerweiterung) aussieht.

+0

Die Umsetzung von Boost im Allgemeinen macht mir Angst, aber jetzt hast du meine Neugier geweckt. – Shirik

+4

@Shirik das kanonische Beispiel für Switch-Hexerei ist [Duffs Gerät] (http://en.wikipedia.org/wiki/Duff's_device): ein Schalter, der mit einer Do-While verflochten ist. – TemplateRex

+0

Ninja'd. Ich bin froh, dass jemand Duffs Gerät erwähnt hat. Ich benutze (selten) diese Art von Zauberei auf Embedded-Systemen, um lange Funktionen zu trennen und den Neustart zu erleichtern. Aber, wenn Sie sich schmutzig fühlen, wenn Sie 'goto' verwenden, sollten Sie wahrscheinlich besonders hart überlegen, bevor Sie Schalter für diese Art von Einstiegspunkt verwenden. – Speed8ump

3

Von den MSDN: -

Erklärungen können an der Spitze der zusammengesetzten Anweisung erscheinen den Schalterkörper bildet, sondern Initialisierungen in den Erklärungen enthalten sind nicht durchgeführt. Die switch-Anweisung überträgt die Steuerung direkt an eine ausführbare Anweisung innerhalb des Rumpfs. Dabei werden die Zeilen umgangen, die Initialisierungen enthalten.

+3

Ich würde MSDN * die Quelle * nicht nennen, wenn überhaupt wäre der Standard * DIE * Quelle. –

+0

Ja, ich habe mir den C++ - Standard angesehen, bin aber nicht weit gekommen. Alles was ich getan habe, war mir selbst zu beweisen, dass es nichts zu beschränken scheint. Es ist eher eines von denen, die "aufgrund einer Regelmangel erlaubt" sind. – Shirik

+0

@MadScienceDreams: Das ist illegal, weil die Initialisierung von x von der Case-Anweisung umgangen wird. – Shirik