Topic: scope of names in for-init-statement


Author: je@bton.ac.uk (John English)
Date: 1995/06/05
Raw View
Mumit Khan (khan@xraylith.wisc.edu) wrote:

: Also, how do people feel about it? I have to go and fix lots of old code
: that relied on using the final value of 'i', so to me it's annoying at the
: very least; fortunately it's very easy to spot. What was the primary reason
: for adding this rule?

Easy enough to "fix" with a global edit: change "for (int i=..." to "int i;
for (i=..." throughout...

: I think we need some pictures and cartoons in the draft to make reading it
: a bit more interesting :-)

Yes, I'll vote for that :-)

--
----------------------------------------------------------------------------
John English <je@brighton.ac.uk>, Dept. of Computing, University of Brighton
  "The Tory party is the cream of society: rich, thick, and full of clots"
----------------------------------------------------------------------------





Author: fjh@munta.cs.mu.OZ.AU (Fergus Henderson)
Date: 1995/06/01
Raw View
chris@alofi.etca.fr (Christian Millour) writes:

>fjh@munta.cs.mu.OZ.AU (Fergus Henderson) writes:
>|> A correction to my post:
>|>
>|> > #define for(a,b,c) if (0) ; else for(a,b,c)
>|>
>|> That should be
>|>
>|>  #define for(a) if (0) ; else for(a)
>
>Any reason for not using
>
>#define for if (0) ; else for
>
>instead ?

No, I think I just got up on the wrong side of the bed that day.
Your suggestion is best; unlike my suggestions, it works even with
`for' statements that have commas in them, such as

 for (i = 0, p = start; i < limit && p != NULL; i++, p = p->next)

--
Fergus Henderson
fjh@cs.mu.oz.au
http://www.cs.mu.oz.au/~fjh





Author: ccwf@locke.klab.caltech.edu (Charles Fu)
Date: 1995/06/02
Raw View
I'm somewhat reluctant to post this in comp.std.c++, but I'm doing so anyways
:-) because it might be very useful for some (and have redirected further
followups elsewhere).

>chris@alofi.etca.fr (Christian Millour) writes:
>>Any reason for not using
>>
>>#define for if (0) ; else for
>>
>>instead ?

In article <9515307.18691@mulga.cs.mu.oz.au>,
Fergus Henderson <fjh@munta.cs.mu.OZ.AU> wrote:
>No, I think I just got up on the wrong side of the bed that day.
>Your suggestion is best; unlike my suggestions, it works even with
>`for' statements that have commas in them

I don't know of any reason not to use this definition in standard C++ programs
(and I, in fact, do so).

However, if mixing C++ and Objective-C code (which, for example, some versions
of gcc will let you do), you can run into problems because it allows C and C++
reserved words to be used as parts of method names.  So,

    [object new:problem for:programmer.project()];

is valid Objective-C++ code.  Fortunately, if you do use gcc, you can use its
nonstandard variable argument macros instead in this case.

-ccwf





Author: ti953017@rzcipa03.rz.tu-bs.de (Andreas Rossberg)
Date: 1995/05/30
Raw View
In article <9514916.10436@mulga.cs.mu.oz.au>,
Fergus Henderson <fjh@munta.cs.mu.OZ.AU> wrote:
>A correction to my post:
>
>> #define for(a,b,c) if (0) ; else for(a,b,c)
>
>That should be
>
> #define for(a) if (0) ; else for(a)

No,

 #define for if (0) ; else for

Otherwise the following won't work, AFAIK:

 for (a = 0, b = 0; ... ; ...) ...


 - Andreas Rossberg






Author: rubenst%occs.nlm.nih.gov (Mike Rubenstein Phoenix Contract)
Date: 1995/05/31
Raw View
Mumit Khan (khan@xraylith.wisc.edu) wrote:
> In article <3qam76$fbc@f111.iassf.easams.com.au>,
> Rohan LENARD <rjl@f111.iassf.easams.com.au> wrote:
> >
> >Yep.  I assume you've made yourself a patch.  If not e-mail me.

> Yes I have. Thanks for the offer though.

> >
> >As I understand it, the primary reason was to allow things like this -
> >
> >  if (Derived* pDerived = dynamic_cast<Derived*>(pBase))
> >  {
> >    // pDerived exists here
> >  }
> >  // pDerived doesn't exist here
> >
> >It would have been *grossly* un-orthogonal to have the scope for this sort
> >of declaration different from that in a for-statement

> I totally agree with both you and Fergus that it would be quite
> inconsistent to leave "for" out of the loop. Fortunately the existing
> code base which used the old behaviour will NOT (hope I'm right on this)
> cause run-time bugs, rather will ALWAYS result in compile-time error
> (unlike trying to convert ANSI C code that uses sizeof('i')).

Unfortunately, you are wrong.  Consider

 int i;
 void f()
 {
   for (int i = 0; i < 10; ++i)
     { /* whatever */ }
   if (i >= 10)
     { /* whatever */ }
 }

Legal before and still legal, but the semantics have changed.

One certainly hopes such code is rare.

--
Mike Rubenstein





Author: rjl@f111.iassf.easams.com.au (Rohan LENARD)
Date: 1995/05/29
Raw View
In article <3q2l8k$hni@news.doit.wisc.edu>,
Mumit Khan <khan@xraylith.wisc.edu> wrote:
>
>Am I right? I noticed that the new GCC snapshot enforces this (in fact it
>doesn't even recognize the -fno-for-scope switch -- it got left out of
>toplev.c when the snapshot was made available), but I'm very curious as to
>what other compiler(s) support this yet.

Yep.  I assume you've made yourself a patch.  If not e-mail me.

>
>Also, how do people feel about it? I have to go and fix lots of old code
>that relied on using the final value of 'i', so to me it's annoying at the
>very least; fortunately it's very easy to spot. What was the primary reason
>for adding this rule?

I guess most people who've used other languages like it.  If you didn't
know of the old rule then you'd intuitively go for the new rule.  It's
not a new idea.  I wrote our companies coding standard nearly two years
ago, and it was being talked about then.  My ARM (Oct 92), talks about
it in the ANSI resolutions section at the back, however I don't think it
was voted on until early last year.

As I understand it, the primary reason was to allow things like this -

  if (Derived* pDerived = dynamic_cast<Derived*>(pBase))
  {
    // pDerived exists here
  }
  // pDerived doesn't exist here

It would have been *grossly* un-orthogonal to have the scope for this sort
of declaration different from that in a for-statement

>
>I think we need some pictures and cartoons in the draft to make reading it
>a bit more interesting :-)

Hmmmm...

RJL
--
----------------------------------------------------------------------------
rjl@iassf.easams.com.au | All quotes can be attributed to my automated quote
Rohan Lenard            | writing tool.  Yours for just $19.95; and if you
+61-2-367-4555          | call now you'll get a free set of steak knives ...





Author: fjh@munta.cs.mu.OZ.AU (Fergus Henderson)
Date: 1995/05/29
Raw View
A correction to my post:

> #define for(a,b,c) if (0) ; else for(a,b,c)

That should be

 #define for(a) if (0) ; else for(a)

--
Fergus Henderson
fjh@cs.mu.oz.au
http://www.cs.mu.oz.au/~fjh





Author: khan@xraylith.wisc.edu (Mumit Khan)
Date: 1995/05/29
Raw View
In article <3qam76$fbc@f111.iassf.easams.com.au>,
Rohan LENARD <rjl@f111.iassf.easams.com.au> wrote:
>
>Yep.  I assume you've made yourself a patch.  If not e-mail me.

Yes I have. Thanks for the offer though.

>
>As I understand it, the primary reason was to allow things like this -
>
>  if (Derived* pDerived = dynamic_cast<Derived*>(pBase))
>  {
>    // pDerived exists here
>  }
>  // pDerived doesn't exist here
>
>It would have been *grossly* un-orthogonal to have the scope for this sort
>of declaration different from that in a for-statement

I totally agree with both you and Fergus that it would be quite
inconsistent to leave "for" out of the loop. Fortunately the existing
code base which used the old behaviour will NOT (hope I'm right on this)
cause run-time bugs, rather will ALWAYS result in compile-time error
(unlike trying to convert ANSI C code that uses sizeof('i')).

thanks for the followup
mumit -- khan@xraylith.wisc.edu
http://www.xraylith.wisc.edu/~khan/







Author: khan@xraylith.wisc.edu (Mumit Khan)
Date: 1995/05/30
Raw View
I had written:
>
>                                               Fortunately the existing
>code base which used the old behaviour will NOT (hope I'm right on this)
>cause run-time bugs, rather will ALWAYS result in compile-time error
>(unlike trying to convert ANSI C code that uses sizeof('i')).
>

And of course I was WRONG as noted in the followups from Rohan Lenard and
Matt Austern. Fortunately GCC (and probably most other compilers) can be
told to warn about shadow'd variables.

mumit






Author: matt@dogbert.lbl.gov (Matthew Austern)
Date: 1995/05/30
Raw View
In article <3qdabp$11nq@news.doit.wisc.edu> khan@xraylith.wisc.edu (Mumit Khan) writes:

> I totally agree with both you and Fergus that it would be quite
> inconsistent to leave "for" out of the loop. Fortunately the existing
> code base which used the old behaviour will NOT (hope I'm right on this)
> cause run-time bugs, rather will ALWAYS result in compile-time error
> (unlike trying to convert ANSI C code that uses sizeof('i')).

Not quite always.  (Is there anything that's "always" true in C++?)
There are a few circumstances in which code using the old scoping
rules for variables declared in for loops will still be legal under
the new rules, but will mean something different.  Consider, for
example, the following fragment:

static int i;

void f()
{
   for (int i = 0; i < 10; i++) {
 // ...
   }

   g(i);   // Refers to local-scope i under old rules,
                                //  and file-scope i under new rules.
}
--
Matt Austern          matt@physics.berkeley.edu
http://dogbert.lbl.gov/~matt





Author: ccwf@locke.klab.caltech.edu (Charles Fu)
Date: 1995/05/30
Raw View
In article <MATT.95May29170409@dogbert.lbl.gov>,
Matthew Austern <matt@physics.berkeley.edu> wrote:
>There are a few circumstances in which code using the old scoping
>rules for variables declared in for loops will still be legal under
>the new rules, but will mean something different.
>  <example deleted>

Perhaps folks could encourage their compiler vendors to provide a
warning when such cases are detected.  For example, gcc has a
-Wshadow flag which will detect potential problems like this example.

-ccwf





Author: chris@alofi.etca.fr (Christian Millour)
Date: 1995/05/30
Raw View
In article <9514916.10436@mulga.cs.mu.OZ.AU>, fjh@munta.cs.mu.OZ.AU (Fergus Henderson) writes:
|> A correction to my post:
|>
|> > #define for(a,b,c) if (0) ; else for(a,b,c)
|>
|> That should be
|>
|>  #define for(a) if (0) ; else for(a)
|>

Any reason for not using

#define for if (0) ; else for

instead ?


--chris@etca.fr

|> --
|> Fergus Henderson
|> fjh@cs.mu.oz.au
|> http://www.cs.mu.oz.au/~fjh





Author: jbuck@synopsys.com (Joe Buck)
Date: 1995/05/30
Raw View
khan@xraylith.wisc.edu (Mumit Khan) writes:
>I totally agree with both you and Fergus that it would be quite
>inconsistent to leave "for" out of the loop. Fortunately the existing
>code base which used the old behaviour will NOT (hope I'm right on this)
>cause run-time bugs, rather will ALWAYS result in compile-time error
>(unlike trying to convert ANSI C code that uses sizeof('i')).

You could get run-time bugs if there are two different variables in
different scopes that use the same name.  This is possible if the for
loop is nested:

#include <iostream.h>

main () {
    int i = 0;
    //
    {
 for (int i = 1; i < 10; i++) // line 7: this is a new i
     ;
 cout << "i = " << i << "\n"; // which i ?
    }
}

Here new compilers print i = 0, old ones print i = 10.

Compilers could detect this condition and warn about it.  The gcc/g++
"-Wshadow" flag may be useful here:

foo.cc:7: warning: declaration of `i' shadows previous local

To aid in conversion, g++ version 2.7.0 (to be released Real Soon Now)
will implement the new "for" scoping rule and will have a flag
"-fno-for-scope" to implement the old rule.  I'd recommend that other
vendors implement similar flags.

Note that code written for the new "for" rule will work fine on compilers
that implement the old rule, as long as the variables declared in for
statements don't shadow other variables of the same name.

--
-- Joe Buck  <jbuck@synopsys.com> (not speaking for Synopsys, Inc)
Phone: +1 415 694 1729





Author: Kevlin Henney <kevlin@wslint.demon.co.uk>
Date: 1995/05/30
Raw View
In article <9514916.10436@mulga.cs.mu.OZ.AU>
           fjh@munta.cs.mu.OZ.AU "Fergus Henderson" writes:

>A correction to my post:
>
>>       #define for(a,b,c) if (0) ; else for(a,b,c)
>
>That should be
>
>        #define for(a) if (0) ; else for(a)

Third time lucky:

 #define for if(0) ; else for

;-)

+-----------------------------+-------------------------------------+
| Kevlin A P Henney           | Can you secure Christmas with an    |
|   kevlin@spuddy.mew.co.uk   | approximation only eighteen million |
| Westinghouse Systems Ltd    | seconds left of the original old    |
|   kevlin@wslint.demon.co.uk | red chimney?         - Jack Kerouac |
+-----------------------------+-------------------------------------+





Author: khan@xraylith.wisc.edu (Mumit Khan)
Date: 1995/05/25
Raw View
The draft says the following in Sec 3.3.1 "Local scope":

[...]
4 Names declared in the for-init-statement, condition,  and  controlling
  expression  parts of if, while, for, and switch statments are local to
  the if, while, for, or  switch  statement  (including  the  controlled
  statement),  and  shall not be redeclared in a subsequent condition or
  controlling expression of that statement nor in the outermost block of
  the controlled statement.
[...]

I take it that this makes the following snippet illegal:

    for (int i = 0; i < foo; ++i) {
 if (bar(i))
     break;
    }

    if (i < foo)
 do_something(i);

Am I right? I noticed that the new GCC snapshot enforces this (in fact it
doesn't even recognize the -fno-for-scope switch -- it got left out of
toplev.c when the snapshot was made available), but I'm very curious as to
what other compiler(s) support this yet.

Also, how do people feel about it? I have to go and fix lots of old code
that relied on using the final value of 'i', so to me it's annoying at the
very least; fortunately it's very easy to spot. What was the primary reason
for adding this rule?

I think we need some pictures and cartoons in the draft to make reading it
a bit more interesting :-)

regards
mumit -- khan@xraylith.wisc.edu
http://www.xraylith.wisc.edu/~khan/  [home of the STL newbie doc]






Author: fwai@armltd.co.uk (Francis Wai)
Date: 1995/05/26
Raw View
khan@xraylith.wisc.edu (Mumit Khan) writes:

>The draft says the following in Sec 3.3.1 "Local scope":
>
>[...]
>4 Names declared in the for-init-statement, condition,  and  controlling
>  expression  parts of if, while, for, and switch statments are local to
>  the if, while, for, or  switch  statement  (including  the  controlled
>  statement),  and  shall not be redeclared in a subsequent condition or
>  controlling expression of that statement nor in the outermost block of
>  the controlled statement.
>[...]

>I take it that this makes the following snippet illegal:

>    for (int i = 0; i < foo; ++i) {
> if (bar(i))
>     break;
>    }

>    if (i < foo)
> do_something(i);

>Am I right?

I'm afraid so. For your example, the Draft Standard says (Sec. 6.5.3)

4. If the for-init-statement is a declaration, the scope of name(s) declared
extends to the end of the for-statement.

Francis


--
e-mail: fwai@armltd.co.uk





Author: fjh@munta.cs.mu.OZ.AU (Fergus Henderson)
Date: 1995/05/28
Raw View
khan@xraylith.wisc.edu (Mumit Khan) writes:

>The draft says the following in Sec 3.3.1 "Local scope":
>4 Names declared in the for-init-statement, condition,  and  controlling
>  expression  parts of if, while, for, and switch statments are local to
>  the if, while, for, or  switch  statement  [...]
>
>I take it that this makes the following snippet illegal:
>
>    for (int i = 0; i < foo; ++i) {
> if (bar(i))
>     break;
>    }
>    if (i < foo)

Yes.

>[...] I'm very curious as to
>what other compiler(s) support this yet.

If your compiler doesn't support it, there is a wonderful hack
to emulate it:

 #define for(a,b,c) if (0) ; else for(a,b,c)

>Also, how do people feel about it?

I think it is a good move.

>I have to go and fix lots of old code
>that relied on using the final value of 'i', so to me it's annoying at the
>very least; fortunately it's very easy to spot. What was the primary reason
>for adding this rule?

The committee decided to allow variables to be introduced in `if' and `while'
statements. I think the main motivation for this was so that one could
emulate a sort of type-case:

 void foo(Base *b) {
  if (Derived1 *d1 = dynamic_cast<Derived *>(p) {
   // code involving d1
  } else if (Derived2 *d2 = dynamic_cast<Derived *>(p) {
   // code involving d2
  } else if (Derived3 *d3 = dynamic_cast<Derived *>(p) {
   // code involving d3
  } else {
   // code involving b
  }
 }

It is pretty clear in this case that the scope must be local.
I think the rationale for changing the behaviour of `for' was
that it would be too confusing and inconsistent if `for' behaved
one way and `if' and `while' behaved the other way.

--
Fergus Henderson
fjh@cs.mu.oz.au
http://www.cs.mu.oz.au/~fjh