no declaration inside for loop header


G

Gary

I have a for loop and try to declare a variable and it complains with
this message.

fun.c:11: error: ‘for’ loop initial declaration used outside C99 mode

line 11: for( int counter = 1; counter <=10; counter++)

This looks illegal I guess with standard C99. So I was looking and
this noob found some information from the C99 document.
---------------------------------------------------
"The declaration part of a for statement shall only declare
identifiers for objects having storage class auto or register."

I am a noob and don't understand some of this language, so I was
looking around in C99 some more.
-----------------------------------------------
"An identifier can denote an object; a function; a tag or a member of
a structure, union, or enumeration; a typedef name; a label name; a
macro name; or a macro parameter. The same identifier can denote
different entities at different points in the program."
"For each different entity that an identifier designates, the
identifier is visible (i.e., can be used) only within a region of
program text called its scope. Different entities designated by the
same identifier either have different scopes, or are in different name
spaces. There are four kinds of scopes: function, file, block, and
function prototype. (A function prototype is a declaration of a
function that declares the types of its parameters.)" If the
declarator or type specifier that declares the identifier appears
inside a block or within the list of parameter declarations in a
function definition, the identifier has block scope, which terminates
at the end of the associated block.
-------------------------------------


If I declare counter like this:
int main (void)
{
int counter;
}

I understand this to have a scope of block. But I didn't understand
what scope I have if I declare in the "for" loop heading (eg. line
11). And I don't understand the storage class auto or register.

Thanks for any insights.
 
Ad

Advertisements

L

luser-ex-troll

Gary said:





No, it's fine in C99. It's only "outside C99 mode" that it's not
fine, and that's what your compiler is telling you. It would appear
that you are invoking your compiler in a non-C99 mode. This in
itself is not a mistake - I always use non-C99 modes myself - but
you have to choose between restricting yourself to C99 (thus making
the above code legal for you) or keeping your options open by
remaining C90-compatible (in which case the above code won't work).



The scope of your 'counter' object is the loop header and loop body:

for(int counter = 1; counter <= 10; counter++) /* in scope here */
{
  counter; /* still in scope */

}

counter; /* error - out of scope */

you can get the best of both by putting a block around the whole
thing:

{ int counter;
for(counter=1; counter<=10; counter++)
counter;
counter;
} /* now its really gone */
counter; /* see? */
 
J

James Kuyper

Richard Heathfield wrote:
....
You don't really need to. Certainly auto is an archaism, and best

Explicit declaration of a variable as 'auto' is archaic; I've never used
a dialect of C in which it wasn't perfectly pointless, though I presume
it might be a carry over from some earlier language where it had some use.

However, variables with implicitly automatic storage class are anything
but archaic. I suspect that most variables in most programs are in that
category, and anyone who dares to read the standard had better
understand what it means when the standard talks about objects with
automatic storage class.
 
K

Keith Thompson

Richard Heathfield said:
James Kuyper said:

Oh, I agree entirely. I was referring specifically to the keyword
itself. I'm sorry for not making that clearer.

Which raises a perhaps interesting terminology issue. There are three
"storage durations": static, automatic, and allocated. But there are
five "storage-class specifiers": typedef, extern, static, auto, and
register. Typedef is a special case, but "static", for example, can
affect storage duration and/or linkage, and "register" doesn't affect
the storage duration (it's automatic with or without the "register"
keyword).

The standard talks about storage-class specifiers, and says what
effect they have on declared objects, but it doesn't seem to say just
what a "storage class" is, if anything.

There are a number of places in the standard that refer to storage
classes. Probably they should instead refer either to storage
durations or to storage-class specifiers. Either that, or the
standard should define just what a "storage class" is, and make it
clear that it's not the same as a storage duration.
 
C

CBFalconer

Keith said:
Which raises a perhaps interesting terminology issue. There are
three "storage durations": static, automatic, and allocated. But
there are five "storage-class specifiers": typedef, extern, static,
auto, and register. Typedef is a special case, but "static", for
example, can affect storage duration and/or linkage, and "register"
doesn't affect the storage duration (it's automatic with or without
the "register" keyword).

I suspect you are raising undeserved cares. 'typedef' isn't
anything new and different, it is basically a convenience.
Similarly 'register' doesn't enforce anything (except eliminating
taking of addresses). This cuts everything back to the three
durations you mentioned.
 
K

Keith Thompson

CBFalconer said:
I suspect you are raising undeserved cares. 'typedef' isn't
anything new and different, it is basically a convenience.
Similarly 'register' doesn't enforce anything (except eliminating
taking of addresses). This cuts everything back to the three
durations you mentioned.

But the standard talks about objects having register storage class.
See, for example, C99 6.5.8p3:

The declaration part of a for statement shall only declare
identifiers for objects having storage class auto or register.

And extern isn't a storage duration at all.
 
Ad

Advertisements

D

Dik T. Winter

> Explicit declaration of a variable as 'auto' is archaic; I've never used
> a dialect of C in which it wasn't perfectly pointless, though I presume
> it might be a carry over from some earlier language where it had some use.

I think it came from B where variables were untyped and you declared one
with either static or auto. It crept into C where declarations that did
not contain a type defaulted to int.
 
B

Ben Bacarisse

Dik T. Winter said:
I think it came from B where variables were untyped and you declared one
with either static or auto.

B had no "static" keyword. An identifier could be declared extern but
an external definition used no keywords at all. auto constituted both
a declaration and a definition (though B was never so rigorous about
maintaining this distinction as C has become).

main()
{
auto i;
extern string, n_strings;
for (i = 0; i < n_strings; i++)
printf("%d: %s*n");
}

strings [] "brave", "new", "world";
n_strings 3;

I know it is churlish to be pedantic about an off-topic language, but
I have a huge (and largely irrational) fondness for B.
 
E

Eric Sosman

Ben said:
[...]
I know it is churlish to be pedantic about an off-topic language, but
I have a huge (and largely irrational) fondness for B.

Any idea why, BBBBBBB
B B
B B
BBBBBB
B B
B B
BBBBBBB en?
 
B

Ben Bacarisse

Eric Sosman said:
Ben said:
[...]
I know it is churlish to be pedantic about an off-topic language, but
I have a huge (and largely irrational) fondness for B.

Any idea why, BBBBBBB
B B
B B
BBBBBB
B B
B B
BBBBBBB en?

Ha! I had honestly not thought of that but you may be right.
 
V

vlsidesign

Gary said:





No, it's fine in C99. It's only "outside C99 mode" that it's not
fine, and that's what your compiler is telling you. It would appear
that you are invoking your compiler in a non-C99 mode. This in
itself is not a mistake - I always use non-C99 modes myself - but
you have to choose between restricting yourself to C99 (thus making
the above code legal for you) or keeping your options open by
remaining C90-compatible (in which case the above code won't work).

Thanks, you're right. I used this compiler command, and it was fine.

gcc -std=c99 for2.c
 
Ad

Advertisements

V

vlsidesign

you can get the best of both by putting a block around the whole
thing:

{   int counter;
    for(counter=1; counter<=10; counter++)
        counter;
    counter;} /* now its really gone */

counter; /* see? */

I see. The brackets are used for grouping. And it seems the
int counter;
has a local scope to that grouping. When the last
counter;
is encountered, it is undeclared (because declaration was not in
main). This is interesting. So whenever you declare a variable like
this, then it's scope is only in that grouping body and below. Cool,
thanks.
 
L

luserXtrog

<snip>






I see. The brackets are used for grouping. And it seems the
  int counter;
has a local scope to that grouping. When the last
  counter;
is encountered, it is undeclared (because declaration was not in
main). This is interesting. So whenever you declare a variable like
this, then it's scope is only in that grouping body and below. Cool,
thanks.

Exactly. The fact that you can declare variables to be local to a
function is a special case of the fact that you can do it to any
block.

If you need a quick variable inside a loop, you can even declare it
with the same name as the index (although then you can't access the
index by that name). Trickery aside, it helps with keeping variable
names short, if you can see on the same screen where they are created
and destroyed.

The only bizarrity of which I'm aware is the switch.

/*assume inclusion of <stdio.h>*/
/*assume tester wraps a function around this bare block*/
{ int i = 0;
switch(i) {
int x = 5; /* probably not gonna happen */
case 0:
printf("woah glad we didn't print x");
break;
case 1:
printf("I dare to know the value of x! %d\n", x);
break;
}
}

The variable is valid, but initialization has obviously been bypassed.
 
Ad

Advertisements

B

Barry Schwarz

I see. The brackets are used for grouping. And it seems the

The braces define a block.
int counter;
has a local scope to that grouping. When the last

The term is block scope.

I assume you meant the last }and what you should have meant was the
corresponding }.
is encountered, it is undeclared (because declaration was not in
main). This is interesting. So whenever you declare a variable like

The term is going out of scope.
this, then it's scope is only in that grouping body and below. Cool,
thanks.

It is in scope only in the block.
 

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

Top