Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Declaring variables in "case" blocks?

Reply
Thread Tools

Declaring variables in "case" blocks?

 
 
Robbie Hatley
Guest
Posts: n/a
 
      07-31-2007

Greetings, group. I just found a weird problem in a program where
a variable declared in a {block} after a "case" keyword was being
treated as having value 0 even though its actual value should
have been something else. An extremely stripped-down version:

int Function (int something)
{
switch(something)
{
case WHATEVER:
{
int DumVar = 72;
// Some code uses DumVar. It seems to see the value
// of DumVar as being 0 ! What the heck???
break;
}
}
}

Is there anything wrong with that? Does it violate some rule
of C that I'm missing? It's almost as if the first time I
try to read Dumvar in the code, it's being redeclared (as int),
redefined, and reinitialized to 0.

When I moved the declaration of DumVar up to the top of the
function, it now works correctly:

int Function (int something-)
{
int DumVar = 72;
switch(something)
{
case WHATEVER:
{
// Code here now sees the value of DumVar as being 72
break;
}
}
}

So am I just missing something, or is my compiler buggy?

(I'm using National Instruments "CVI" compiler for this;
I haven't tested this on a more common compiler such as GCC.)

--
Cheers,
Robbie Hatley
lone wolf aatt well dott com
triple-dubya dott Tustin Free Zone dott org


 
Reply With Quote
 
 
 
 
Keith Thompson
Guest
Posts: n/a
 
      07-31-2007
"Robbie Hatley" <(E-Mail Removed)> writes:
> Greetings, group. I just found a weird problem in a program where
> a variable declared in a {block} after a "case" keyword was being
> treated as having value 0 even though its actual value should
> have been something else. An extremely stripped-down version:
>
> int Function (int something)
> {
> switch(something)
> {
> case WHATEVER:
> {
> int DumVar = 72;
> // Some code uses DumVar. It seems to see the value
> // of DumVar as being 0 ! What the heck???
> break;
> }
> }
> }


I think you've stripped down your code so far that you've eliminated
the error. The above is valid, and code that refers to DumVar will
see its value as 72. You'd have been better off posting a small
compilable program, so you could confirm that the problem is still
there.

But here's an example that illustrates the problem you're having:

#include <stdio.h>
int main(void)
{
int x = 42;
switch(x) {
int DumVar = 72;
case 42:
printf("ok, x = %d, DumVar = %d\n", x, DumVar);
break;
default:
printf("Huh?\n");
break;
}
return 0;
}

The output I get is:

ok, x = 42, DumVar = 1628438944

after a compiler warning:

c.c:6: warning: unreachable code at beginning of switch statement

The problem is that control jumps directly from the 'switch' to the
appropriate 'case' label, in this case to 'case 42:'. After that,
DumVar is visible, but you've skipped over its initialization.

You can safely declare variables within a block following a case
label, but not within a block that's the entire body of the switch
statement.

For more fun with switch statements, see question 20.35 in the
comp.lang.c FAQ, <http://www.c-faq.com/> (Duff's Device).

--
Keith Thompson (The_Other_Keith) http://www.velocityreviews.com/forums/(E-Mail Removed) <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
 
 
 
Robbie Hatley
Guest
Posts: n/a
 
      07-31-2007

"Keith Thompson" <(E-Mail Removed)> wrote:

> "Robbie Hatley" <(E-Mail Removed)> writes:
> > Greetings, group. I just found a weird problem in a program where
> > a variable declared in a {block} after a "case" keyword was being
> > treated as having value 0 even though its actual value should
> > have been something else. An extremely stripped-down version:
> >
> > int Function (int something)
> > {
> > switch(something)
> > {
> > case WHATEVER:
> > {
> > int DumVar = 72;
> > // Some code uses DumVar. It seems to see the value
> > // of DumVar as being 0 ! What the heck???
> > break;
> > }
> > }
> > }

>
> I think you've stripped down your code so far that you've eliminated
> the error.


Maybe so.

> The above is valid


That's what I was wondering about. Thanks.

> and code that refers to DumVar will see its value as 72.


Theoretically, yes.

In practice (in my program, with my compiler), I was seeing 0,
which is why I was so puzzled.

> You'd have been better off posting a small compilable program,
> so you could confirm that the problem is still there.


I (mostly) did. If you #define WHATEVER, then call Function()
from main(), it will compile and run.

Hmmm... let me try that.

Ok, I just compiled and ran my stripped-down version here,
with a sprintf() of DumVar to a char buffer, and printed the buffer
in a popup message box. It displays as "72". Oops. Problem went
away. Weird.

I'm truly perplexed. I'll have to try to reproduce this bizarre
bug again.

> But here's an example that illustrates the problem you're having:
>
> #include <stdio.h>
> int main(void)
> {
> int x = 42;
> switch(x) {
> int DumVar = 72;
> case 42:
> printf("ok, x = %d, DumVar = %d\n", x, DumVar);
> break;
> default:
> printf("Huh?\n");
> break;
> }
> return 0;
> }


Nice try, but that's not my problem. I was careful to put
the variable declaration at the top of a {block}, just under a
CASE label, like so:

#include <stdio.h>
int main(void)
{
int x = 42;
switch(x) {
case 42:
{
int DumVar = 72;
printf("ok, x = %d, DumVar = %d\n", x, DumVar);
break;
}
default:
printf("Huh?\n");
break;
}
return 0;
}

and I was getting "DumVar = 0". Definitely wasn't a large
value (uninitialized RAM garbage) as you're getting here:

> The output I get is:
>
> ok, x = 42, DumVar = 1628438944
>
> after a compiler warning:
>
> c.c:6: warning: unreachable code at beginning of switch statement
>
> The problem is that control jumps directly from the 'switch' to the
> appropriate 'case' label, in this case to 'case 42:'. After that,
> DumVar is visible, but you've skipped over its initialization.


Yep! I've seen that one bite even highly-experienced co-workers.
Since your declaration is never executed, your compiler declares
the variable as int for you, allocates some memory, but doesn't
initialize it to anything. So it's value could be anything from
-(2^31) to +(2^31)-1. (Assuming 32-bit int, 2's comp. rep.)

> You can safely declare variables within a block following a case
> label, but not within a block that's the entire body of the switch
> statement.


Well, you could... but the code will never execute.

> For more fun with switch statements, see question 20.35 in the
> comp.lang.c FAQ, <http://www.c-faq.com/> (Duff's Device).


Whoa! It's actually legal to jump into the middle of a do loop
that way?! Cool machine!

--
Cheers,
Robbie Hatley
lone wolf aatt well dott com
triple-dubya dott Tustin Free Zone dott org


 
Reply With Quote
 
Flash Gordon
Guest
Posts: n/a
 
      07-31-2007
Robbie Hatley wrote, On 31/07/07 21:20:
> "Keith Thompson" <(E-Mail Removed)> wrote:
>
>> "Robbie Hatley" <(E-Mail Removed)> writes:


<snip>

>> You'd have been better off posting a small compilable program,
>> so you could confirm that the problem is still there.

>
> I (mostly) did. If you #define WHATEVER, then call Function()
> from main(), it will compile and run.
>
> Hmmm... let me try that.
>
> Ok, I just compiled and ran my stripped-down version here,
> with a sprintf() of DumVar to a char buffer, and printed the buffer
> in a popup message box. It displays as "72". Oops. Problem went
> away. Weird.


<snip>

This is why you should always reduce your code to a small compilable
example that exhibits the problem (obviously, if the problem is it not
compiling then it does not need to be compilable!). There is no point
other people trying to debug a problem in code that does not exhibit the
problem.
--
Flash Gordon
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      07-31-2007
"Robbie Hatley" <(E-Mail Removed)> writes:
> "Keith Thompson" <(E-Mail Removed)> wrote:
>> "Robbie Hatley" <(E-Mail Removed)> writes:
>> > Greetings, group. I just found a weird problem in a program where
>> > a variable declared in a {block} after a "case" keyword was being
>> > treated as having value 0 even though its actual value should
>> > have been something else. An extremely stripped-down version:
>> >
>> > int Function (int something)
>> > {
>> > switch(something)
>> > {
>> > case WHATEVER:
>> > {
>> > int DumVar = 72;
>> > // Some code uses DumVar. It seems to see the value
>> > // of DumVar as being 0 ! What the heck???
>> > break;
>> > }
>> > }
>> > }

>>
>> I think you've stripped down your code so far that you've eliminated
>> the error.

>
> Maybe so.
>
>> The above is valid

>
> That's what I was wondering about. Thanks.
>
>> and code that refers to DumVar will see its value as 72.

>
> Theoretically, yes.
>
> In practice (in my program, with my compiler), I was seeing 0,
> which is why I was so puzzled.


You weren't seeing 0 with the code that you posted. Without seeing
code that does display 0, I can't make any definitive comments.

>> You'd have been better off posting a small compilable program,
>> so you could confirm that the problem is still there.

>
> I (mostly) did. If you #define WHATEVER, then call Function()
> from main(), it will compile and run.
>
> Hmmm... let me try that.
>
> Ok, I just compiled and ran my stripped-down version here,
> with a sprintf() of DumVar to a char buffer, and printed the buffer
> in a popup message box. It displays as "72". Oops. Problem went
> away. Weird.


There's nothing weird about it. The code you posted doesn't exhibit
the error.

You need to create your own complete stripped-down program, and run it
yourself to exhibit the error, *before* you post it here.

> I'm truly perplexed. I'll have to try to reproduce this bizarre
> bug again.


Please do.

Do you still have the original code that exhibited the problem? It's
probably too big to post here, but be sure you save a copy of it so
you can use it as a basis for creating something that you can post.

>> But here's an example that illustrates the problem you're having:
>>
>> #include <stdio.h>
>> int main(void)
>> {
>> int x = 42;
>> switch(x) {
>> int DumVar = 72;
>> case 42:
>> printf("ok, x = %d, DumVar = %d\n", x, DumVar);
>> break;
>> default:
>> printf("Huh?\n");
>> break;
>> }
>> return 0;
>> }

>
> Nice try, but that's not my problem. I was careful to put
> the variable declaration at the top of a {block}, just under a
> CASE label, like so:
>
> #include <stdio.h>
> int main(void)
> {
> int x = 42;
> switch(x) {
> case 42:
> {
> int DumVar = 72;
> printf("ok, x = %d, DumVar = %d\n", x, DumVar);
> break;
> }
> default:
> printf("Huh?\n");
> break;
> }
> return 0;
> }
>
> and I was getting "DumVar = 0". Definitely wasn't a large
> value (uninitialized RAM garbage) as you're getting here:


Most likely you're mistaken, or perhaps you're having some other
problem that's not related to the switch statement.

>> The output I get is:
>>
>> ok, x = 42, DumVar = 1628438944
>>
>> after a compiler warning:
>>
>> c.c:6: warning: unreachable code at beginning of switch statement
>>
>> The problem is that control jumps directly from the 'switch' to the
>> appropriate 'case' label, in this case to 'case 42:'. After that,
>> DumVar is visible, but you've skipped over its initialization.

>
> Yep! I've seen that one bite even highly-experienced co-workers.
> Since your declaration is never executed, your compiler declares
> the variable as int for you, allocates some memory, but doesn't
> initialize it to anything. So it's value could be anything from
> -(2^31) to +(2^31)-1. (Assuming 32-bit int, 2's comp. rep.)
>
>> You can safely declare variables within a block following a case
>> label, but not within a block that's the entire body of the switch
>> statement.

>
> Well, you could... but the code will never execute.


The initializer, if any, will be skipped -- but the variable will
exist. This is not a good idea, though, since you can always declare
it in an outer scope.

>> For more fun with switch statements, see question 20.35 in the
>> comp.lang.c FAQ, <http://www.c-faq.com/> (Duff's Device).

>
> Whoa! It's actually legal to jump into the middle of a do loop
> that way?! Cool machine!


It's the language, not any particular machine. Duff's Device is legal
and portable (though there's some controversy about this).

A switch statement is a lower-level construct than it appears to be.
It's really nothing more than a computed goto within a single
statement (which can be a block). The error of skipping an initializer
in a switch statement is really no different than this:

#include <stdio.h>
int main(void)
{
goto LABEL;
{
int x = 42;
LABEL:
printf("x = %d\n", x);
}
return 0;
}

As for the problem you're having in your code, no offense, but I don't
believe that it's as you describe it. If you can post an actual
program that exhibits the problem (by "actual program" I mean
something that anyone else can copy-and-paste, compile, link, and
execute, with no modifications), then we'll be glad to look at it.
But all we've seen so far is code that doesn't exhibit the problem,
and code that does exhibit a problem but for reasons different from
what you describe.

It's possible that you've run across either an obscure corner of the
language that I'm not thinking of, or a compiler bug, but that's not
the way to bet.

--
Keith Thompson (The_Other_Keith) (E-Mail Removed) <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
Robbie Hatley
Guest
Posts: n/a
 
      07-31-2007

"Keith Thompson" <(E-Mail Removed)> wrote:

> As for the problem you're having in your code, no offense,


None taken.

> but I don't believe that it's as you describe it.


I didn't save a copy of the version that had the problem,
but I did manually reconstruct it by moving the variable
declarations back into the block under the case label.

However, the problem did *NOT* recur!

I suspect now that it was something like this:

int Func(int x)
{
switch (x)
{
case 8:
{
int DumVar = 72;
char Blat[51] = {'\0'};
sprintf(Blat, "DumVar = %d\n", Dumvar); // ERROR
MessagePopup("!!!", Blat); // prints "DumVar = 0"
}
}
}

See the problem? It's on the line marked "ERROR". It's
almost invisible. Hint: has to do with case.



I'm about 80% certain now that something like that was the
problem. I can never be totally sure what happened, though.

Next time some bizarre bug like this happens, I'll
be sure to save a zip snapshot of source (my poor-man's
version of version control) before making any changes.
That way, I can post a stripped-down, compilable program
that actually does exhibit the bug.

Anyway, thanks for your help.

--
Cheers,
Robbie Hatley
lone wolf aatt well dott com
triple-dubya dott Tustin Free Zone dott org


 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      07-31-2007
"Robbie Hatley" <(E-Mail Removed)> writes:
[...]
> I suspect now that it was something like this:
>
> int Func(int x)
> {
> switch (x)
> {
> case 8:
> {
> int DumVar = 72;
> char Blat[51] = {'\0'};
> sprintf(Blat, "DumVar = %d\n", Dumvar); // ERROR
> MessagePopup("!!!", Blat); // prints "DumVar = 0"
> }
> }
> }
>
> See the problem? It's on the line marked "ERROR". It's
> almost invisible. Hint: has to do with case.


Got it. So you had a local variable named 'DumVar', and a variable in
an outer scope named 'Dumvar'? I assume you didn't use those names in
your actual code, but you might find that a more consistent naming
convention will help you avoid such problems in the future.

[...]

> Next time some bizarre bug like this happens, I'll
> be sure to save a zip snapshot of source (my poor-man's
> version of version control) before making any changes.
> That way, I can post a stripped-down, compilable program
> that actually does exhibit the bug.


<OT>
Consider using an actual version control system. There are several
free ones out there, and they more than pay for themselves. (I use
RCS and CVS myself.)
</OT>

--
Keith Thompson (The_Other_Keith) (E-Mail Removed) <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
Army1987
Guest
Posts: n/a
 
      07-31-2007
On Tue, 31 Jul 2007 22:49:30 +0000, Robbie Hatley wrote:

> I suspect now that it was something like this:
>
> int Func(int x)
> {
> switch (x)
> {
> case 8:
> {
> int DumVar = 72;
> char Blat[51] = {'\0'};
> sprintf(Blat, "DumVar = %d\n", Dumvar); // ERROR
> MessagePopup("!!!", Blat); // prints "DumVar = 0"
> }
> }
> }
>
> See the problem? It's on the line marked "ERROR". It's
> almost invisible. Hint: has to do with case.

I wouldn't expect it to compile at all, unless there is a Dumvar
with a small v declared in an outer scope.
(And do they claim that CamelCase is better than dum_var because
you could unintentionally spell the latter with a wrong number of
underscores? Hum...)
--
Army1987 (Replace "NOSPAM" with "email")
"Never attribute to malice that which can be adequately explained
by stupidity." -- R. J. Hanlon (?)

 
Reply With Quote
 
Don Bruder
Guest
Posts: n/a
 
      07-31-2007
In article <_%Ori.207881$(E-Mail Removed)>,
"Robbie Hatley" <(E-Mail Removed)> wrote:

> "Keith Thompson" <(E-Mail Removed)> wrote:
>
> > As for the problem you're having in your code, no offense,

>
> None taken.
>
> > but I don't believe that it's as you describe it.

>
> I didn't save a copy of the version that had the problem,
> but I did manually reconstruct it by moving the variable
> declarations back into the block under the case label.
>
> However, the problem did *NOT* recur!
>
> I suspect now that it was something like this:
>
> int Func(int x)
> {
> switch (x)
> {
> case 8:
> {
> int DumVar = 72;
> char Blat[51] = {'\0'};
> sprintf(Blat, "DumVar = %d\n", Dumvar); // ERROR
> MessagePopup("!!!", Blat); // prints "DumVar = 0"
> }
> }
> }
>
> See the problem? It's on the line marked "ERROR". It's
> almost invisible. Hint: has to do with case.


If that's the actual problem, you would have (Or at least SHOULD have)
gotten an "undefined identifier: Dumvar" type of error from the
compiler, since, syntactically, that's exactly what you've got going on.

--
Don Bruder - (E-Mail Removed) - If your "From:" address isn't on my whitelist,
or the subject of the message doesn't contain the exact text "PopperAndShadow"
somewhere, any message sent to this address will go in the garbage without my
ever knowing it arrived. Sorry... <http://www.sonic.net/~dakidd> for more info
 
Reply With Quote
 
David Mathog
Guest
Posts: n/a
 
      08-01-2007
Robbie Hatley wrote:
> I didn't save a copy of the version that had the problem,
> but I did manually reconstruct it by moving the variable
> declarations back into the block under the case label.
>
> However, the problem did *NOT* recur!


Use valgrind or another memory access checker on problems
like this. One reason DumVar could have the wrong value
is an invalid memory access stomping on it. Putting in print
statements sometimes moves code around and "fixes" that sort
of problem, but not really of course.

>
> I suspect now that it was something like this:


Didn't you keep the broken version of the program???

> sprintf(Blat, "DumVar = %d\n", Dumvar); // ERROR


That should have thrown a compiler error, unless Dumvar was
declared elsewhere. Using both DumVar and Dumvar in the same function
would have been, well, "Dum"!

Regards,

David Mathog
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
help in declaring variables =?Utf-8?B?QXNoYQ==?= ASP .Net 2 12-31-2004 05:18 AM
Basic JSP - declaring variables??? Joey P Java 0 10-10-2004 01:48 PM
Newbie: Declaring Variables Steven K ASP .Net 5 02-28-2004 08:21 PM
Declaring variables - best practice? Rob Meade ASP .Net 2 11-24-2003 03:01 PM
Declaring variables with global scope (Newbie Question)! Mortal Wombat ASP .Net 3 08-07-2003 11:06 AM



Advertisments