Connecting Tech Pros Worldwide Help | Site Map

variable declaration inside switch case label

  #1  
Old June 17th, 2007, 04:25 PM
subramanian100in@yahoo.com, India
Guest
 
Posts: 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 ?

  #2  
Old June 17th, 2007, 04:35 PM
rsprawls
Guest
 
Posts: n/a

re: variable declaration inside switch case label


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

Quote:
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?

  #3  
Old June 17th, 2007, 05:05 PM
John Harrison
Guest
 
Posts: n/a

re: variable declaration inside switch case label


subramanian100in@yahoo.com, India wrote:
Quote:
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
  #4  
Old June 17th, 2007, 06:35 PM
Bharath
Guest
 
Posts: n/a

re: variable declaration inside switch case label


On Jun 17, 10:56 am, John Harrison <john_androni...@hotmail.com>
wrote:
Quote:
subramanian10...@yahoo.com, India wrote:
Quote:
Consider the following program:
>
Quote:
#include <iostream>
>
Quote:
using namespace std;
>
Quote:
int main()
{
int i;
>
Quote:
cin >i;
>
Quote:
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;
}
>
Quote:
return 0;
}
>
Quote:
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
>
Quote:
int case_1 = 1;
>
Quote:
inside case 1.
>
Quote:
But there is no compilation error for the declaration
>
Quote:
int case_2 = 2;
>
Quote:
inside case 2.
>
Quote:
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

  #5  
Old June 17th, 2007, 07:15 PM
John Harrison
Guest
 
Posts: n/a

re: variable declaration inside switch case label


>
Quote:
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
  #6  
Old June 17th, 2007, 07:25 PM
Pete Becker
Guest
 
Posts: n/a

re: variable declaration inside switch case label


John Harrison wrote:
Quote:
Quote:
>>
>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)
  #7  
Old June 17th, 2007, 08:15 PM
John Harrison
Guest
 
Posts: n/a

re: variable declaration inside switch case label


Pete Becker wrote:
Quote:
John Harrison wrote:
Quote:
Quote:
>>>
>>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

  #8  
Old June 17th, 2007, 08:15 PM
Pete Becker
Guest
 
Posts: n/a

re: variable declaration inside switch case label


John Harrison wrote:
Quote:
>
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)
  #9  
Old June 17th, 2007, 08:35 PM
John Harrison
Guest
 
Posts: n/a

re: variable declaration inside switch case label


Pete Becker wrote:
Quote:
John Harrison wrote:
Quote:
>>
>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
  #10  
Old June 17th, 2007, 10:15 PM
James Kanze
Guest
 
Posts: n/a

re: variable declaration inside switch case label


On Jun 17, 8:11 pm, John Harrison <john_androni...@hotmail.comwrote:
Quote:
Quote:
John - Thanks for good information. Is this documented somewhere?
Quote:
Well it's documented in the C++ standard, section 6.7.3, but I guess any
good C++ book would cover this.
Quote:
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
Quote:
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;
}
Quote:
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: james.kanze@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

  #11  
Old June 17th, 2007, 10:15 PM
=?ISO-8859-1?Q?Erik_Wikstr=F6m?=
Guest
 
Posts: n/a

re: variable declaration inside switch case label


On 2007-06-17 21:27, John Harrison wrote:
Quote:
Pete Becker wrote:
Quote:
>John Harrison wrote:
Quote:
>>>
>>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
  #12  
Old June 18th, 2007, 08:25 AM
John Harrison
Guest
 
Posts: n/a

re: variable declaration inside switch case label


Erik Wikström wrote:
Quote:
On 2007-06-17 21:27, John Harrison wrote:
Quote:
>Pete Becker wrote:
Quote:
>>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
  #13  
Old June 18th, 2007, 10:15 AM
=?ISO-8859-1?Q?Erik_Wikstr=F6m?=
Guest
 
Posts: n/a

re: variable declaration inside switch case label


On 2007-06-18 09:21, John Harrison wrote:
Quote:
Erik Wikström wrote:
Quote:
>On 2007-06-17 21:27, John Harrison wrote:
Quote:
>>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.
Quote:
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
  #14  
Old June 18th, 2007, 01:35 PM
Pete Becker
Guest
 
Posts: n/a

re: variable declaration inside switch case label


John Harrison wrote:
Quote:
>
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)
  #15  
Old June 18th, 2007, 01:45 PM
James Kanze
Guest
 
Posts: n/a

re: variable declaration inside switch case label


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

[...]
Quote:
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.)
Quote:
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
Quote:
int i = 1;
Quote:
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:james.kanze@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

Closed Thread


Similar Threads
Thread Thread Starter Forum Replies Last Post
.Net frameword Resources ( vb.net , asp.net etc...) shamirza answers 0 January 17th, 2007 08:05 AM
Learning C with Older books ?. Jhon smith answers 90 November 14th, 2005 06:39 PM
scope and linkage rule, very confusing! pembed2003 answers 5 November 14th, 2005 07:29 AM
PEP 263 status check John Roth answers 27 July 18th, 2005 02:37 PM