Scope of block-local variables

C

Chris Croughton

In the following code, what is the scope of the variables?

int main(void)
{
int var;
for (var = 0; var < 10; ++var)
{
int var = var + 5;
printf("%d\n", var);
}
return 0;
}

I'm certain that I have read (here in clc) that a variable's scope
doesn't start until the end of its definition, so saying

int var = var + 5;

is valid and sets the block-local variable var to the value of the outer
variable var. However, GCC (2.95.4, 3.0.4, 3.3.3) disagrees with me.
Have I got confused, or is GCC broken in that way?

(Yes, that code is confusing. However, there are times, like in a
function-like macro, when it can occur.)

Chris C
 
S

S.Tobias

Chris Croughton said:
int main(void)
{
int var;
for (var = 0; var < 10; ++var)
{
int var = var + 5;
printf("%d\n", var);
}
return 0;
}
I'm certain that I have read (here in clc) that a variable's scope
doesn't start until the end of its definition, so saying

The scope of a variable starts where its complete declarator ends
(cf. 6.2.1#7 and 6.7.5), which for inner `var' is:
int var
(the things after that are "=" and initializer).
int var = var + 5;
is valid and sets the block-local variable var to the value of the outer
variable var. However, GCC (2.95.4, 3.0.4, 3.3.3) disagrees with me.
Have I got confused, or is GCC broken in that way?

GCC is right.

I haven't found any nice example in the C Std, so I'll quote
one from C++:
The point of declaration for a name is immediately after its complete
declarator (clause 8) and before its initializer (if any), except as
noted below. [Example:
int x = 12;
{ int x = x; }
Here the second x is initialized with its own (indeterminate) value. ]

+++++

As a bonus, for VLA I think this should be correct:
int var = 7;
{
double var[var]; //second var refers to outer int var
}
 
C

Chris Croughton

The scope of a variable starts where its complete declarator ends
(cf. 6.2.1#7 and 6.7.5), which for inner `var' is:
int var
(the things after that are "=" and initializer).

Ah, I was confusing its declaration with the definition. I never have
got those two straight (my gut feeling is that the meanings are the
other way round).
GCC is right.

However,

int Mongolia = 1;
{
int war = Mongolia, Mongolia = war;
...
}

has the intended effect, because war is declared and set to Outer
Mongolia before Inner Mongolia is declared and set to war (and hence to
Outer Mongolia). Which is what I want for macros to force single
evaluation of the arguments without having name clashes...

(No, I haven't been drinking. Perhaps I should...)
I haven't found any nice example in the C Std, so I'll quote
one from C++:
The point of declaration for a name is immediately after its complete
declarator (clause 8) and before its initializer (if any), except as
noted below. [Example:
int x = 12;
{ int x = x; }
Here the second x is initialized with its own (indeterminate) value. ]

I couldn't find it in the C standard, either.
+++++

As a bonus, for VLA I think this should be correct:
int var = 7;
{
double var[var]; //second var refers to outer int var
}

Yes, I think it should. Whether it works for any particular compiler is
left as an exercise for the reader.

Thanks...

Chris C
 
S

S.Tobias

Chris Croughton said:
On 27 Nov 2004 16:15:02 GMT, S.Tobias

Sorry, I was wrong here (cf. 6.7 and 6.7.5). In declaration
int var = 5;
the declarator is:
var
Ah, I was confusing its declaration with the definition.

No, you confuse declarator with declaration.

*Declaration* is a form which introduces a name into a scope (declarations
can be nested - eg. function declaration may declare its parameters).

Declaration is a *definition*, when it defines an object of function
(6.7#5) (every definition is a declaration, but some declarations are
not definitions).

*Declarator* is just part of declaration which includes the identifier
(name) and its type category (and may include nested declarations).
extern int const * const * p; //declarator: * const * p
int f(double d) {/*...*/} //declarator: f(double d)
I don't think we need the idea of "declarator" for anything other
than grammatical analysis.

(Funny thing is that in 6.7 the syntax for a declaration does not
encompass function definition, which is actually directly admitted
in the footnote.)

int Mongolia = 1;
{
int war = Mongolia, Mongolia = war;
...
}
has the intended effect,
Yes.

because war is declared and set to Outer
Mongolia before Inner Mongolia is declared and set to war (and hence to
Outer Mongolia).
:)

Which is what I want for macros to force single
evaluation of the arguments without having name clashes...

Now this is interesting, how do you manage to do it?
 
C

Chris Croughton

Sorry, I was wrong here (cf. 6.7 and 6.7.5). In declaration
int var = 5;
the declarator is:
var

OK, but the point (for me) is that it is complete when var has been
completely declared and before it is initialised..
No, you confuse declarator with declaration.

*Declaration* is a form which introduces a name into a scope (declarations
can be nested - eg. function declaration may declare its parameters).

Declaration is a *definition*, when it defines an object of function
(6.7#5) (every definition is a declaration, but some declarations are
not definitions).

*Declarator* is just part of declaration which includes the identifier
(name) and its type category (and may include nested declarations).
extern int const * const * p; //declarator: * const * p
int f(double d) {/*...*/} //declarator: f(double d)
I don't think we need the idea of "declarator" for anything other
than grammatical analysis.

Ah, right. I think the terms are confusing anyway. And have done since
I encountered them in K&R almost 30 years ago...
(Funny thing is that in 6.7 the syntax for a declaration does not
encompass function definition, which is actually directly admitted
in the footnote.)

Hmm. Perhaps they had trouble with it as well said:

I started thinking in English and the Outer and Inner suggested Mongolia
Now this is interesting, how do you manage to do it?

It turns out that the way I thought of doing it still doesn't work.
However, it does mean that I can give the first variable a name no one
would ever use (_XyZzY_24C41_PlUgH_) and then use a shorter one (like
'i') in the rest of the macro.

Chris C
 
S

S.Tobias

It turns out that the way I thought of doing it still doesn't work.

Ha, I knew it! :-D
However, it does mean that I can give the first variable a name no one
would ever use (_XyZzY_24C41_PlUgH_) and then use a shorter one (like
'i') in the rest of the macro.

All identifiers with regexps __.* and _[[:upper:]].* are reserved,
so I would change your name to _xyZzY_24C41_PlUgH_ (I stumbled on it
once, so I'm careful ever since).

I believe "no one would ever use" is the only technique.
 
C

Chris Croughton

Ha, I knew it! :-D

I thought "Ah, that solves it" but like a lot of 'eureka' monoents it
didn't last.
However, it does mean that I can give the first variable a name no one
would ever use (_XyZzY_24C41_PlUgH_) and then use a shorter one (like
'i') in the rest of the macro.

All identifiers with regexps __.* and _[[:upper:]].* are reserved,
so I would change your name to _xyZzY_24C41_PlUgH_ (I stumbled on it
once, so I'm careful ever since).

Oops, that's true. Just invert the case. The centre part should, of
course, been 124C_41...

I seem to remember that at one time identifiers with the form

str[[:lower:]].*

were also reserved (and possibly some other prefixes used by library
functions) but can't find that in the C99 spec. Was this true, or was
it someone's extension?
I believe "no one would ever use" is the only technique.

Indeed. What I really want is inline template functions, but even if
they were in C (and I don't seriously think that they should be) in a
future standard I still couldn't use them until all previous compilers
had become unused...

Chris C
 
M

Mark McIntyre

I seem to remember that at one time identifiers with the form

str[[:lower:]].*

were also reserved (and possibly some other prefixes used by library
functions) but can't find that in the C99 spec. Was this true, or was
it someone's extension?

7.26 Future library directions
All external names described below are reserved no matter what headers are
included by the program.
.....
7.26.11 String handling <string.h>
1 Function names that begin with str, mem, or wcs and a lowercase letter
may be added to the declarations in the <string.h> header.
 
S

S.Tobias

Chris Croughton said:
On 27 Nov 2004 22:34:49 GMT, S.Tobias
Chris Croughton said:
On 27 Nov 2004 20:49:59 GMT, S.Tobias
Chris Croughton <[email protected]> wrote:

All identifiers with regexps __.* and _[[:upper:]].* are reserved,

Me wrong again: ^__.* and ^_[[:upper:]].*
Oops, that's true. Just invert the case. The centre part should, of
course, been 124C_41...

The center was all right, it's what starts and identifier that counts.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,006
Messages
2,570,265
Members
46,860
Latest member
JeremiahCo

Latest Threads

Top