Variablendeklaration in case-Label



  • Ich hatte heute mal einen Fehler, den ich bisher jetzt nicht replizieren kann. Dabei ging es um eine normale switch/case Konstruktion, so wie hier:

    switch(num)
    {
       case 1:
          int var;
       break;
    }
    

    Das hat dann einen Fehler verursacht, die Meldung lautete in etwa "declaration of var skipped by case-label". Das ganze war ein Error, hat also tatsächlich den Compile-Vorgang gestoppt. Ich weiß leider atm nicht, wie eine Konstruktion aussieht, die diesen Fehler verursacht, aber falls jemand mehr weiß, bitte mal sagen, was ich hier meine. 😉

    Danach würde mich interessieren, wieso das ein Fehler war. Den Variablendeklarationen sind ja scheinbar in Ordnung.



  • Das Problem ist das Verhalten von switch bei fehlendem break:

    switch(x) {
    case 0:  int i = 0;
    default: cout << i;
    }
    

    Wenn das erlaubt waere, wuerde die Variable i im default-Zweig nicht initialisiert, nicht mal deklariert, sein.



  • das ist ein besonders nettes (und unbekanntes) feature.
    folgendes kompiliert beispielsweise perfekt (genauso wie der code des OPs kompilieren sollte):

    switch(x) 
    {
       case 0:  int i;
       default: cin >> i;
    }
    

    das problem bei Christophs code liegt in der initialisierung ( = 0; )



  • Das Problem besteht soweit ich weiss eher, wenn man bei einem case Label keinen neuen Scope eroeffnet:

    int i = 2;
        switch(i)
        {
        case 1:
          int x = 0; // Fehler, MSVC++ bringt hier afair die vom OP genannte Meldung
          break;
    
        case 2:
          break;
        }
    
    int i = 2;
        switch(i)
        {
        case 1:
          {
            int x = 0; // geht
          }
          break;
    
        case 2:
          break;
        }
    

    Edit: nochmal ausfuehrlich



  • einmal grundsätzlich: dieses verhalten ist nicht auf switch beschränkt.
    kurz gesagt ist es einfach nicht möglich, zu einem punkt zu springen, wo ein objekt bereits sichtbar ist von einem punkt aus, an dem es das nicht ist:

    class Foo 
    {
    public:
       Foo () {}
    };
    
    int main ()
    {
       goto label; //fehler!
    
       Foo foo;
    
       label: return 0;
    }
    
    //beachte: rückwärts springen ist erlaubt
    int main ()
    {
       start: Foo foo;//... und wieder erschaffen
       goto start;    //Foo wird zerstört...
    }
    

    allerdings gibt es eine ausnahme: ist das objekt ein POD-typ und wird nicht manuell initialisiert, ist der sprung in ordnung.

    struct POD {};
    struct NoPOD
    {
      NoPOD () {}
    };
    
    int main ()
    {
       goto ok; //OK
    
       POD pod;
       ok: goto no_no; //fehler
    
       NoPOD nopod;
       no_no: goto nope; //fehler
    
       POD pod = POD();
       nope:  
    }
    

Anmelden zum Antworten