Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't variables be declared in a switch statement?

I've always wondered this - why can't you declare variables after a case label in a switch statement? In C++ you can declare variables pretty much anywhere (and declaring them close to first use is obviously a good thing) but the following still won't work:

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

The above gives me the following error (MSC):

initialization of 'newVal' is skipped by 'case' label

This seems to be a limitation in other languages too. Why is this such a problem?

like image 480
Rob Avatar asked Sep 18 '08 13:09

Rob


People also ask

Can you declare variables in a switch statement?

You can still declare variables in switch statements, you just have to put curly brackets around the code after the case label.

Which variable is not allowed in switch statement?

The switch statement doesn't accept arguments of type long, float, double,boolean or any object besides String.

Can we declare variables in switch-case Java?

Do not declare variables inside a switch statement before the first case label. According to the C Standard, 6.8.

What variables are used in a switch statement?

Syntax. The variable used in a switch statement can only be integers, convertable integers (byte, short, char), strings and enums. You can have any number of case statements within a switch. Each case is followed by the value to be compared to and a colon.


2 Answers

Case statements are only labels. This means the compiler will interpret this as a jump directly to the label. In C++, the problem here is one of scope. Your curly brackets define the scope as everything inside the switch statement. This means that you are left with a scope where a jump will be performed further into the code skipping the initialization.

The correct way to handle this is to define a scope specific to that case statement and define your variable within it:

switch (val) {    case VAL:   {   // This will work   int newVal = 42;     break; } case ANOTHER_VAL:   ... break; } 
like image 168
TJ Seabrooks Avatar answered Oct 04 '22 03:10

TJ Seabrooks


This question was originally tagged as c and c++ at the same time. The original code is indeed invalid in both C and C++, but for completely different unrelated reasons.

  • In C++ this code is invalid because the case ANOTHER_VAL: label jumps into the scope of variable newVal bypassing its initialization. Jumps that bypass initialization of automatic objects are illegal in C++. This side of the issue is correctly addressed by most answers.

  • However, in C language bypassing variable initialization is not an error. Jumping into the scope of a variable over its initialization is legal in C. It simply means that the variable is left uninitialized. The original code does not compile in C for a completely different reason. Label case VAL: in the original code is attached to the declaration of variable newVal. In C language declarations are not statements. They cannot be labeled. And this is what causes the error when this code is interpreted as C code.

      switch (val)     {     case VAL:             /* <- C error is here */     int newVal = 42;       break;   case ANOTHER_VAL:     /* <- C++ error is here */     ...     break;   } 

    Adding an extra {} block fixes both C++ and C problems, even though these problems happen to be very different. On the C++ side it restricts the scope of newVal, making sure that case ANOTHER_VAL: no longer jumps into that scope, which eliminates the C++ issue. On the C side that extra {} introduces a compound statement, thus making the case VAL: label to apply to a statement, which eliminates the C issue.

  • In C case the problem can be easily solved without the {}. Just add an empty statement after the case VAL: label and the code will become valid

      switch (val)     {     case VAL:;            /* Now it works in C! */     int newVal = 42;       break;   case ANOTHER_VAL:       ...     break;   } 

    Note that even though it is now valid from C point of view, it remains invalid from C++ point of view.

  • Symmetrically, in C++ case the the problem can be easily solved without the {}. Just remove the initializer from variable declaration and the code will become valid

      switch (val)     {     case VAL:      int newVal;     newVal = 42;       break;   case ANOTHER_VAL:     /* Now it works in C++! */     ...     break;   } 

    Note that even though it is now valid from C++ point of view, it remains invalid from C point of view.

like image 32
AnT Avatar answered Oct 04 '22 05:10

AnT