By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
424,950 Members | 1,008 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 424,950 IT Pros & Developers. It's quick & easy.

variable declaration inside switch case label

P: n/a
Consider the following program:

#include <iostream>

using namespace std;

int main()
{
int i;

cin >i;

switch ( i )
{
case 1:
int case_1 = 1;
cout << "case_1 " << case_1 << endl;
break;
case 2:
int case_2 = 2;
cout << "case_2 " << case_2 << endl;
break;
}

return 0;
}

If a variable is declared inside any case label except the last case
label, I am getting compilation error. In this program I am getting
compilation error for the declaration

int case_1 = 1;

inside case 1.

But there is no compilation error for the declaration

int case_2 = 2;

inside case 2.

Kindly explain what is the difference and why is the declaration not
allowed in other case labels but allowed in the last case label in a
switch ?

Jun 17 '07 #1
Share this Question
Share on Google+
14 Replies


P: n/a
On Jun 17, 10:23 am, "subramanian10...@yahoo.com, India"
<subramanian10...@yahoo.comwrote:

If a variable is declared inside any case label except the last case
label, I am getting compilation error. In this program I am getting
compilation error for the declaration

int case_1 = 1;

inside case 1.

But there is no compilation error for the declaration

int case_2 = 2;

inside case 2.

Kindly explain what is the difference and why is the declaration not
allowed in other case labels but allowed in the last case label in a
switch ?
It's been a long, long time since I programmed and I'm starting to
pick it back up, so bear with me if I'm wrong:

The fact that erroring out on the first case statement and not on the
second leads me to believe it's not reporting the error on case_2
because it's not processing anymore after case_1, because it's already
in error. Have you tried removing the int case_1 = 1 to see if it
errs on the case_2 = 2 line?

Jun 17 '07 #2

P: n/a
su**************@yahoo.com, India wrote:
Consider the following program:

#include <iostream>

using namespace std;

int main()
{
int i;

cin >i;

switch ( i )
{
case 1:
int case_1 = 1;
cout << "case_1 " << case_1 << endl;
break;
case 2:
int case_2 = 2;
cout << "case_2 " << case_2 << endl;
break;
}

return 0;
}

If a variable is declared inside any case label except the last case
label, I am getting compilation error. In this program I am getting
compilation error for the declaration

int case_1 = 1;

inside case 1.

But there is no compilation error for the declaration

int case_2 = 2;

inside case 2.

Kindly explain what is the difference and why is the declaration not
allowed in other case labels but allowed in the last case label in a
switch ?
Because it's a rule of C++ that a jump cannot pass over a variable
declaration in the same scope. So when you jump to case 2, you pass over
the variable declaration in case 1. But the variable declaration in the
last case is OK, because it is never jumped over.

The reason for the rule is that if you allowed a jump over a variable
declaration it would be very hard for the compiler to work out whether
to call a destructor for that variable. If you had jumped over the
variable declaration you would not need to call the destructor, if you
had not jumped then you would.

If you want to decalre variable inside switch statements, do it like this

switch ( i )
{
case 1:
{
int case_1 = 1;
cout << "case_1 " << case_1 << endl;
}
break;
case 2:
{
int case_2 = 2;
cout << "case_2 " << case_2 << endl;
}
break;
}

The extra { and } mean that the compiler has no trouble working out when
to call destructors.

Of there are no ddestructors for int variables, but there could be for
other variable types, and it was decided to made all variables the same
for this rule.

john
Jun 17 '07 #3

P: n/a
On Jun 17, 10:56 am, John Harrison <john_androni...@hotmail.com>
wrote:
subramanian10...@yahoo.com, India wrote:
Consider the following program:
#include <iostream>
using namespace std;
int main()
{
int i;
cin >i;
switch ( i )
{
case 1:
int case_1 = 1;
cout << "case_1 " << case_1 << endl;
break;
case 2:
int case_2 = 2;
cout << "case_2 " << case_2 << endl;
break;
}
return 0;
}
If a variable is declared inside any case label except the last case
label, I am getting compilation error. In this program I am getting
compilation error for the declaration
int case_1 = 1;
inside case 1.
But there is no compilation error for the declaration
int case_2 = 2;
inside case 2.
Kindly explain what is the difference and why is the declaration not
allowed in other case labels but allowed in the last case label in a
switch ?

Because it's a rule of C++ that a jump cannot pass over a variable
declaration in the same scope. So when you jump to case 2, you pass over
the variable declaration in case 1. But the variable declaration in the
last case is OK, because it is never jumped over.

The reason for the rule is that if you allowed a jump over a variable
declaration it would be very hard for the compiler to work out whether
to call a destructor for that variable. If you had jumped over the
variable declaration you would not need to call the destructor, if you
had not jumped then you would.

If you want to decalre variable inside switch statements, do it like this

switch ( i )
{
case 1:
{
int case_1 = 1;
cout << "case_1 " << case_1 << endl;
}
break;
case 2:
{
int case_2 = 2;
cout << "case_2 " << case_2 << endl;
}
break;
}

The extra { and } mean that the compiler has no trouble working out when
to call destructors.

Of there are no ddestructors for int variables, but there could be for
other variable types, and it was decided to made all variables the same
for this rule.

john
John - Thanks for good information. Is this documented somewhere?

Bharath

Jun 17 '07 #4

P: n/a
>
John - Thanks for good information. Is this documented somewhere?

Bharath
Well it's documented in the C++ standard, section 6.7.3, but I guess any
good C++ book would cover this.

Looking at the standard though, there's an exception to this rule which
I wasn't aware of. If the variable is a POD type (int is a POD type for
instance) and if the declaration does not have an initialiser then you
are allowed to 'jump' the variable declartion. I.e. if you had written

switch ( i )
{
case 1:
int case_1;
case_1 = 1;
cout << "case_1 " << case_1 << endl;
break;
case 2:
int case_2;
case_2 = 2;
cout << "case_2 " << case_2 << endl;
break;
}

the code would been legal (assuming I'm reading this right). Not sure
what the rationale is for that.

john
Jun 17 '07 #5

P: n/a
John Harrison wrote:
>>
John - Thanks for good information. Is this documented somewhere?

Bharath

Well it's documented in the C++ standard, section 6.7.3, but I guess any
good C++ book would cover this.

Looking at the standard though, there's an exception to this rule which
I wasn't aware of. If the variable is a POD type (int is a POD type for
instance) and if the declaration does not have an initialiser then you
are allowed to 'jump' the variable declartion. I.e. if you had written

switch ( i )
{
case 1:
int case_1;
case_1 = 1;
cout << "case_1 " << case_1 << endl;
break;
case 2:
int case_2;
case_2 = 2;
cout << "case_2 " << case_2 << endl;
break;
}

the code would been legal (assuming I'm reading this right). Not sure
what the rationale is for that.
The issue is skipping the initialization of a variable. If there's no
initialization, then there's nothing to skip, so the jump is harmless.

--

-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)
Jun 17 '07 #6

P: n/a
Pete Becker wrote:
John Harrison wrote:
>>>
John - Thanks for good information. Is this documented somewhere?

Bharath

Well it's documented in the C++ standard, section 6.7.3, but I guess
any good C++ book would cover this.

Looking at the standard though, there's an exception to this rule
which I wasn't aware of. If the variable is a POD type (int is a POD
type for instance) and if the declaration does not have an initialiser
then you are allowed to 'jump' the variable declartion. I.e. if you
had written

switch ( i )
{
case 1:
int case_1;
case_1 = 1;
cout << "case_1 " << case_1 << endl;
break;
case 2:
int case_2;
case_2 = 2;
cout << "case_2 " << case_2 << endl;
break;
}

the code would been legal (assuming I'm reading this right). Not sure
what the rationale is for that.

The issue is skipping the initialization of a variable. If there's no
initialization, then there's nothing to skip, so the jump is harmless.
I don't understand. For a POD type there doesn't seem to be any
difference between

T x = y;

and

T x;
x = y;

so why is there this situation where on is legal and the other isn't. If
the initialisation (in the first case) is harmful, why isn't the
assignment in the second case? Why ban the first case when the same
effect can be achieved by the second case?

john

Jun 17 '07 #7

P: n/a
John Harrison wrote:
>
I don't understand. For a POD type there doesn't seem to be any
difference between

T x = y;

and

T x;
x = y;

so why is there this situation where on is legal and the other isn't. If
the initialisation (in the first case) is harmful, why isn't the
assignment in the second case? Why ban the first case when the same
effect can be achieved by the second case?
How would you succinctly describe the second case in order to write a
rule prohibiting skipping it? The rule is simply that skipping
initializers isn't allowed.

--

-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)
Jun 17 '07 #8

P: n/a
Pete Becker wrote:
John Harrison wrote:
>>
I don't understand. For a POD type there doesn't seem to be any
difference between

T x = y;

and

T x;
x = y;

so why is there this situation where on is legal and the other isn't.
If the initialisation (in the first case) is harmful, why isn't the
assignment in the second case? Why ban the first case when the same
effect can be achieved by the second case?

How would you succinctly describe the second case in order to write a
rule prohibiting skipping it? The rule is simply that skipping
initializers isn't allowed.
Well granted that would be difficult. But why not allow both cases? That
what I'm suggesting. In other words non-POD declarations cannot be
skipped, but POD ones can with or without initialiser. What would be the
harm?

john
Jun 17 '07 #9

P: n/a
On Jun 17, 8:11 pm, John Harrison <john_androni...@hotmail.comwrote:
John - Thanks for good information. Is this documented somewhere?
Well it's documented in the C++ standard, section 6.7.3, but I guess any
good C++ book would cover this.
Looking at the standard though, there's an exception to this rule which
I wasn't aware of. If the variable is a POD type (int is a POD type for
instance) and if the declaration does not have an initialiser then you
are allowed to 'jump' the variable declartion. I.e. if you had written
switch ( i )
{
case 1:
int case_1;
case_1 = 1;
cout << "case_1 " << case_1 << endl;
break;
case 2:
int case_2;
case_2 = 2;
cout << "case_2 " << case_2 << endl;
break;
}
the code would been legal (assuming I'm reading this right). Not sure
what the rationale is for that.
The problem is that if i == 2, and you jump to case 2, case_1 is
in scope. If case_1 had an initializer (either explicit
initialization, or a non-trivial constructor), presumable any
use of it without initialization is an error. if it doesn't,
presumably, you've covered your bets otherwise.

I think someone mentionned destructors. In fact, it has nothing
to do with destructors; the destructor of both case_1 and case_2
will be called when they go out of scope, at the closing brace
of the switch. Again, presumably, if the object didn't have a
non-trivial constructor, and wasn't initialized, presumably,
calling the destructor on it is OK.

You gave the key to understanding the rules in your first
answer, indirectly. A switch (and the break in each of the
cases) has the semantics of a goto. The real rule is that you
are not allowed to jump over a non-trivial initialization (but
leaving scope by any means causes the destructors to be called).

--
James Kanze (Gabi Software) email: ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Jun 17 '07 #10

P: n/a
On 2007-06-17 21:27, John Harrison wrote:
Pete Becker wrote:
>John Harrison wrote:
>>>
I don't understand. For a POD type there doesn't seem to be any
difference between

T x = y;

and

T x;
x = y;

so why is there this situation where on is legal and the other isn't.
If the initialisation (in the first case) is harmful, why isn't the
assignment in the second case? Why ban the first case when the same
effect can be achieved by the second case?

How would you succinctly describe the second case in order to write a
rule prohibiting skipping it? The rule is simply that skipping
initializers isn't allowed.

Well granted that would be difficult. But why not allow both cases? That
what I'm suggesting. In other words non-POD declarations cannot be
skipped, but POD ones can with or without initialiser. What would be the
harm?
It's quite late, so I might miss something here but are you suggesting
that it should be allowed to skip initialization of POD-types? Consider
the following (while I hope to god that a pointer is a POD*):

int* p;
goto skip;
p = new int;
skip:
*p = 1;

I just can't see any way to make it safe to skip initialization without
introducing a lot of special cases.

* And should a pointer not be a POD-type we can just replace it with
struct POD { int* p}

--
Erik Wikström
Jun 17 '07 #11

P: n/a
Erik Wikström wrote:
On 2007-06-17 21:27, John Harrison wrote:
>Pete Becker wrote:
>>John Harrison wrote:

I don't understand. For a POD type there doesn't seem to be any
difference between

T x = y;

and

T x;
x = y;

so why is there this situation where on is legal and the other
isn't. If the initialisation (in the first case) is harmful, why
isn't the assignment in the second case? Why ban the first case when
the same effect can be achieved by the second case?
How would you succinctly describe the second case in order to write a
rule prohibiting skipping it? The rule is simply that skipping
initializers isn't allowed.

Well granted that would be difficult. But why not allow both cases?
That what I'm suggesting. In other words non-POD declarations cannot
be skipped, but POD ones can with or without initialiser. What would
be the harm?

It's quite late, so I might miss something here but are you suggesting
that it should be allowed to skip initialization of POD-types? Consider
the following (while I hope to god that a pointer is a POD*):

int* p;
goto skip;
p = new int;
skip:
*p = 1;

I just can't see any way to make it safe to skip initialization without
introducing a lot of special cases.

* And should a pointer not be a POD-type we can just replace it with
struct POD { int* p}
I don't understand, your code compiles. Will crash at run time of
course, but that's not the point.

I'm talking about the fact that it is a compile error to skip an
initialisation.

// illegal
goto skip;
int* p = new int;
skip:
*p = 1;

// legal
goto skip;
int* p;
p = new int;
skip:
*p = 1;

This is very strange, and I still don't understand.

john
Jun 18 '07 #12

P: n/a
On 2007-06-18 09:21, John Harrison wrote:
Erik Wikström wrote:
>On 2007-06-17 21:27, John Harrison wrote:
>>Pete Becker wrote:
John Harrison wrote:
>
I don't understand. For a POD type there doesn't seem to be any
difference between
>
T x = y;
>
and
>
T x;
x = y;
>
so why is there this situation where on is legal and the other
isn't. If the initialisation (in the first case) is harmful, why
isn't the assignment in the second case? Why ban the first case when
the same effect can be achieved by the second case?
>

How would you succinctly describe the second case in order to write a
rule prohibiting skipping it? The rule is simply that skipping
initializers isn't allowed.
Well granted that would be difficult. But why not allow both cases?
That what I'm suggesting. In other words non-POD declarations cannot
be skipped, but POD ones can with or without initialiser. What would
be the harm?

It's quite late, so I might miss something here but are you suggesting
that it should be allowed to skip initialization of POD-types? Consider
the following (while I hope to god that a pointer is a POD*):

int* p;
goto skip;
p = new int;
skip:
*p = 1;

I just can't see any way to make it safe to skip initialization without
introducing a lot of special cases.

* And should a pointer not be a POD-type we can just replace it with
struct POD { int* p}

I don't understand, your code compiles. Will crash at run time of
course, but that's not the point.
Oh, right, it was a bit too late to post.
I'm talking about the fact that it is a compile error to skip an
initialisation.

// illegal
goto skip;
int* p = new int;
skip:
*p = 1;

// legal
goto skip;
int* p;
p = new int;
skip:
*p = 1;

This is very strange, and I still don't understand.
The rule is that it's not allowed to skip a declaration of a type unless
the type is POD and not initialized. The reason you can't skip a
declaration of a non-POD is that it will always initialize the variable
(by running the constructor).

The following is pure speculation on my part but I would guess that the
reason you can't skip a declaration of a POD-type with initialization is
because that would violate the intent of the programmer. If I write
something like

int i = 1;

it means that I want there to be a variable named i with the value of 1,
and I can depend on it being 1 until I change it. The reason you are
allowed to skip a declaration (without initialization) is probably
because it's easy to implement and allows you to do some things you
wouldn't otherwise (though you can always rewrite to get the same effect).

--
Erik Wikström
Jun 18 '07 #13

P: n/a
John Harrison wrote:
>
I don't understand, your code compiles. Will crash at run time of
course, but that's not the point.
That IS the point. When an object is explicitly initialized, it's
because that initialization is important. If you haven't bothered to
initialize it, it's because you don't care whether it's initialized, and
subsequent code is responsible for handling that uninitialized object
correctly.

--

-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)
Jun 18 '07 #14

P: n/a
On Jun 18, 11:14 am, Erik Wikström <Erik-wikst...@telia.comwrote:

[...]
The rule is that it's not allowed to skip a declaration of a type unless
the type is POD and not initialized. The reason you can't skip a
declaration of a non-POD is that it will always initialize the variable
(by running the constructor).
Not quite. The rule is that it is not allowed to skip a
definition of a type if the definition has an explicit
initializer or if the type has a non-trivial constructor.
According to the standard, something like the following is
legal:

struct S
{
~S() { std::cout << "coucou, me voila" << std::endl ; }
} ;

goto skip ;
S anS ;
skip:
; // ...

(In practice, of course, it doesn't make a difference, because
if we provide a user defined destructor, there's a reason, and
that reason will almost always render the construct
non-trivial.)
The following is pure speculation on my part but I would guess that the
reason you can't skip a declaration of a POD-type with initialization is
because that would violate the intent of the programmer. If I write
something like
int i = 1;
it means that I want there to be a variable named i with the value of 1,
and I can depend on it being 1 until I change it. The reason you are
allowed to skip a declaration (without initialization) is probably
because it's easy to implement and allows you to do some things you
wouldn't otherwise (though you can always rewrite to get the same effect).
More or less, yes. I rather suspect that the idea was
originally to apply it to classes which had a user-defined
constructor; it is guaranteed that no instance of such a class
shall exist without the constructor having been run on it. But
the logic necessary to verify this easily extends to the more
general case of any initialization; doing more, on the other
hand, requires a lot more work.

--
James Kanze (GABI Software, from CAI) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Jun 18 '07 #15

This discussion thread is closed

Replies have been disabled for this discussion.