1149 Stimmen

Warum können Variablen nicht in einer switch-Anweisung deklariert werden?

Ich habe mich schon immer gefragt, warum man Variablen nicht nach einem Case-Label in einer switch-Anweisung deklarieren kann. I

switch (val)  
{  
case VAL:  
  // This won't work
  int newVal = 42;  
  break;
case ANOTHER_VAL:  
  ...
  break;
}  

Dies führt zu der folgenden Fehlermeldung (MSC):

Initialisierung von 'newVal' wird durch 'case'-Etikett übersprungen

Dies scheint auch in anderen Sprachen eine Einschränkung zu sein. Warum ist dies ein solches Problem?

21voto

emk Punkte 58032

Sie können das nicht tun, weil case Etiketten sind eigentlich nur Einstiegspunkte in den enthaltenen Block.

Dies wird am deutlichsten illustriert durch Duff's Gerät . Hier ist ein Code aus Wikipedia:

strcpy(char *to, char *from, size_t count) {
    int n = (count + 7) / 8;
    switch (count % 8) {
    case 0: do { *to = *from++;
    case 7:      *to = *from++;
    case 6:      *to = *from++;
    case 5:      *to = *from++;
    case 4:      *to = *from++;
    case 3:      *to = *from++;
    case 2:      *to = *from++;
    case 1:      *to = *from++;
               } while (--n > 0);
    }
}

Beachten Sie, wie die case Etiketten ignorieren die Blockgrenzen völlig. Ja, das ist böse. Aber deshalb funktioniert Ihr Codebeispiel nicht. Das Springen zu einem case Etikett ist dasselbe wie die Verwendung von goto Sie dürfen also nicht mit einem Konstruktor über eine lokale Variable springen.

Wie mehrere andere Poster bereits angedeutet haben, müssen Sie einen eigenen Block einrichten:

switch (...) {
    case FOO: {
        MyObject x(...);
        ...
        break; 
    }
    ...
 }

16voto

MrZebra Punkte 11337

Die meisten der bisherigen Antworten sind in einem Punkt falsch: Sie peut Variablen nach der case-Anweisung deklarieren, aber Sie kann nicht sie zu initialisieren:

case 1:
    int x; // Works
    int y = 0; // Error, initialization is skipped by case
    break;
case 2:
    ...

Wie bereits erwähnt, kann man dies gut umgehen, indem man Klammern verwendet, um einen Anwendungsbereich für Ihren Fall zu schaffen.

13voto

Jeremy Punkte 2228

Mein liebster böser Schaltertrick besteht darin, ein if(0) zu verwenden, um eine unerwünschte Fallbezeichnung zu übergehen.

switch(val)
{
case 0:
// Do something
if (0) {
case 1:
// Do something else
}
case 2:
// Do something in all cases
}

Aber sehr böse.

10voto

Dan Shield Punkte 1328

Versuchen Sie dies:

switch (val)
{
    case VAL:
    {
        int newVal = 42;
    }
    break;
}

7voto

slim Punkte 37932

Bedenken Sie:

switch(val)
{
case VAL:
   int newVal = 42;
default:
   int newVal = 23;
}

In Ermangelung von break-Anweisungen wird newVal manchmal zweimal deklariert, und man weiß bis zur Laufzeit nicht, ob dies der Fall ist. Ich vermute, dass die Einschränkung auf diese Art von Verwirrung zurückzuführen ist. Was wäre der Geltungsbereich von newVal? Die Konvention würde vorschreiben, dass es sich um den gesamten switch-Block (zwischen den geschweiften Klammern) handeln würde.

Ich bin kein C++-Programmierer, aber in C:

switch(val) {
    int x;
    case VAL:
        x=1;
}

Funktioniert gut. Das Deklarieren einer Variablen innerhalb eines Switch-Blocks ist in Ordnung. Die Deklaration nach einem Case Guard ist es nicht.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X