473,387 Members | 1,698 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

variable declaration inside switch case label

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
14 13005
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
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
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
>
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
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
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
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
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
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
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
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
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
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
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 thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

83
by: Alexander Zatvornitskiy | last post by:
Hello All! I'am novice in python, and I find one very bad thing (from my point of view) in language. There is no keyword or syntax to declare variable, like 'var' in Pascal, or special syntax in...
3
by: Anoop | last post by:
Hi guys i have a piece of code main() { switch(...) { case 1: {
5
by: Neil Zanella | last post by:
Hello, Unlike in pre-C99 versions of C where variables can only be defined at the beginning of blocks, C99 allows variables to be defined in arbitrary places inside blocks. However, gcc 3.2.2...
23
by: Russ Chinoy | last post by:
Hi, This may be a totally newbie question, but I'm stumped. If I have a function such as: function DoSomething(strVarName) { ..... }
7
by: gyan | last post by:
follwing code gives error: 1 #include<iostream.h> 2 int main() 3 { 4 int a=5,b; 5 switch(a){ 6 case 1: 7 {b=5; 8 break; 9 }
4
by: Ray | last post by:
Hello, I think I've had JavaScript variable scope figured out, can you please see if I've got it correctly? * Variables can be local or global * When a variable is declared outside any...
26
by: Alexander Korsunsky | last post by:
Hi! I have some code that looks similar to this: -------------------------------------------- char array = "abcdefghij"; for (int i = 0; i < 10; i++) {
11
by: cmk128 | last post by:
Hi I am using gcc void peter(){ int x; LABEL1: int y; <--------------- Error } Why ? and how to fix it?
8
by: Dom | last post by:
This is a little tricky, but I think the error I'm getting isn't valid. The compiler just doesn't know my logic. MyObject o; switch (IntVariable) { case 1: o = new MyObject() break;
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.