Why Can't Variables Be Declared in a Switch Statement

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

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;
}

Can't declare variable in switch case [duplicate]

Opposite to C++, in C declarations are not statements and labels may precede only statements.

Placing a null statement after the label

case 4:;

you made that the label does not precede now a declaration.

Another approach is to use a compound statement after the label and to place the declaration inside the compound statement like

    case 4:
{
int res = 1;
printf("%d",res);
break;
}

c++ Declaring a variable inside a switch statement

The reason why some variable declarations are not allowed in a switch statement is: it is illegal for switch-based control flow to jump over a variable initialisation.

In your case, I assume the type of commonData has trivial initialisation (no constructor and no non-trivial members), so declaring it is perfectly fine, as would be declaring just int someInt;. However, int someInt = 1; is not allowed, since the initialisation would be skipped whenever mode is not abc.

I can't quite see what you'd get from declaring commonData only once, except for saving some typing at the cost of obscuring the code ("where did commonData come from?" when reading a case block), which is never a good trade. So I would just use {} inside each case "block" and declare commonData in each one which needs it. Or declare commonData above the switch.

But if you really want the same commonData to be shared by all cases and yet local to the switch block, you can fine-tune the scopes. Something like this:

switch(mode)
{
SomeType commonData;
case abc:
{
...
commonData = manager->getDataByIndex(this->Data.particularData);
int someInt = 1;
...
break;
}
case xyz:
...
commonData = manager->getDataByIndex(this->Data.particularData);
break;
default:
...
break;
}

or this:

switch(mode)
{
case abc:
SomeType commonData;
...
commonData = manager->getDataByIndex(this->Data.particularData);
{
int someInt = 1;
...
break;
}
case xyz:
...
commonData = manager->getDataByIndex(this->Data.particularData);
break;
default:
...
break;
}

But please, think of the next maintainer, and don't play such tricks.


The answer above assumes struct commonData; is actually a "typo" in your code: literally, it would forward-declare a type, and not declare a variable. But that matches neither usage in the rest of your code, nor the text of your question, so I took the liberty of fixing this.

Why is declaring a variable in switch statement allowed? but not declaration + initialization?

The case label functions as a target of a goto statement.

The C++ standard states in [stmt.dcl]/3:

It is possible to transfer into a block, but not in a way that bypasses declarations with initialization.

So the below will fail:

case 'a':
int x = 4; //will fail

whereas the following will not fail:

case 'a':
int x; // this is ok
x = 4;

In response to the OP's edit:

In this particular case, just the declaration makes x visible throughout the switch statement as there are no braces {} surrounding it.
So x can be used in with the other cases as well although the compiler will warn about using it uninitialized. Note that reading of an uninitialized variable is undefined behavior.

To answer the last part of your question:

Suppose the declaration with initialization was allowed it would mean that that particular value of x (4 in this case) would have to be used in other cases as well.
Then it would seem as if code for multiple cases was executed. So this is not allowed.

c++: why can we declare a variable in case of switch

There are actually 2 questions:

1. Why can I declare a variable after case label?

It's because in C++ label has to be in form:

N3337 6.1/1

labeled-statement:

...

  • attribute-specifier-seqopt case constant-expression : statement

...

And in C++ declaration statement is also considered as statement (as opposed to C):

N3337 6/1:

statement:

...

  • declaration-statement

...

2. Why can I jump over variable declaration and then use it?

Because:
N3337 6.7/3

It is possible to transfer into a block, but not in a way that bypasses declarations with initialization. A
program that jumps
(The transfer from the condition of a switch statement to a case label is considered a jump in this respect.)

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).

Since k is of scalar type, and is not initialized at point of declaration jumping over it's declaration is possible. This is semantically equivalent:

goto label;

int x;

label:
cout << x << endl;

However this wouldn't work if x was initialized at point of declaration:

 goto label;

int x = 58; //error, jumping over declaration with initialization

label:
cout << x << endl;

Why we can not define a variable twice in switch? [duplicate]

if the break statements are not used, Then we know that the following cases will be executed. So if you are permitted to declare in both cases that will cause a conflict. For example

switch(x) {

case 1:
int a = 1; // i have removed the break;
case 2:
int a = 2; // now what will happen here :)
break;
}

Declaration of a variable inside a swich case

The reason is that the lexical scope of both declarations is the entire switch body; all the cases share that scope.

That is, in terms of lexical scope, it's like writing

{
int a;
int a;
}

The solution is to enclose the declarations in another braced scope.

switch(whatever)
{
case 1:
{
int a;
break;
}

case 2:
{
int a;
break;
}
}

(Whether you put the break inside or outside the braces is mostly a matter of taste. I prefer to include the entire case.)

This works for the same reason that this "switch-free" snippet works:

{
{
int a;
}
{
int a;
}
}


Related Topics



Leave a reply



Submit