Error: Jump to case label

The problem is that variables declared in one case are still visible in the subsequent cases unless an explicit { } block is used, but they will not be initialized because the initialization code belongs to another case.

In the following code, if foo equals 1, everything is ok, but if it equals 2, we'll accidentally use the i variable which does exist but probably contains garbage.

switch(foo) {
  case 1:
    int i = 42; // i exists all the way to the end of the switch
    dostuff(i);
    break;
  case 2:
    dostuff(i*2); // i is *also* in scope here, but is not initialized!
}

Wrapping the case in an explicit block solves the problem:

switch(foo) {
  case 1:
    {
        int i = 42; // i only exists within the { }
        dostuff(i);
        break;
    }
  case 2:
    dostuff(123); // Now you cannot use i accidentally
}

Edit

To further elaborate, switch statements are just a particularly fancy kind of a goto. Here's an analoguous piece of code exhibiting the same issue but using a goto instead of a switch:

int main() {
    if(rand() % 2) // Toss a coin
        goto end;

    int i = 42;

  end:
    // We either skipped the declaration of i or not,
    // but either way the variable i exists here, because
    // variable scopes are resolved at compile time.
    // Whether the *initialization* code was run, though,
    // depends on whether rand returned 0 or 1.
    std::cout << i;
}

Declaration of new variables in case statements is what causing problems. Enclosing all case statements in {} will limit the scope of newly declared variables to the currently executing case which solves the problem.

switch(choice)
{
    case 1: {
       // .......
    }break;
    case 2: {
       // .......
    }break;
    case 3: {
       // .......
    }break;
}    

C++11 standard on jumping over some initializations

JohannesD gave an explanation, now for the standards.

The C++11 N3337 standard draft 6.7 "Declaration statement" says:

3 It is possible to transfer into a block, but not in a way that bypasses declarations with initialization. A program that jumps (87) from a point where a variable with automatic storage duration is not in scope to a point where it is in scope is ill-formed unless the variable has scalar type, class type with a trivial default constructor and a trivial destructor, a cv-qualified version of one of these types, or an array of one of the preceding types and is declared without an initializer (8.5).

87) The transfer from the condition of a switch statement to a case label is considered a jump in this respect.

[ Example:

void f() {
   // ...
  goto lx;    // ill-formed: jump into scope of a
  // ...
ly:
  X a = 1;
  // ...
lx:
  goto ly;    // OK, jump implies destructor
              // call for a followed by construction
              // again immediately following label ly
}

— end example ]

As of GCC 5.2, the error message now says:

crosses initialization of

C

C allows it: c99 goto past initialization

The C99 N1256 standard draft Annex I "Common warnings" says:

2 A block with initialization of an object that has automatic storage duration is jumped into

Tags:

C++