🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

10 total messages Started by Bob Kline Mon, 06 Nov 1995 05:02
New treatment of 'for (int i ...'
#2433
Author: Bob Kline
Date: Mon, 06 Nov 1995 05:02
51 lines
2923 bytes
I post this comment on the new treatment of the variable i in the for
loop 'for (int i ...)' not so much to say that I disagree with the 
change (in theory, anyway, I think it was a correct decision) as a
warning about how much code this will break.  I was apprehensive 
from the outset when I first discovered the change, but the extent
of the problems to be faced as a result hadn't really hit home until
I undertook the task of building groff for Windows NT.  It was a
real eye-opener to see how much reliance there was on the assumption
that the variable's lifetime continues until the end of the scop
enclosing the 'for' loop.  The worst was tbl, whose source compiled
without error and linked fine, even produced reasonable-looking
output until you looked closely and found out spanned columns 
weren't being handled properly.  It took quite a bit of digging to
find the culprit.  It looks a lot simpler in this boiled-down
version, but the original function was lengthy and convoluted
enough to make spotting the problem non-trivial:

   ...
   int c = in.get();
   ...
   while (...) {
      for (int c = 0; c < ncolumns; c++) { 
         ...
      }
      for (c = 0; c < ncolumns; c++) { // wrong c!
         ...
      }
   }
   ...
   for (;;) {
      if (c == tab_char || c == '\n') // oops! c isn't what it's
                                      //  supposed to be ...

I'd say it's hard to fault the authors of the original code, who
were just following the advice frequently given to C++ programmers
to delay creation of a variable until as close to its first use as 
possible (of course, it would have helped if they had used a
different name for the second variable :->} ).

I expect this is just a small taste of similar fun to come.

--
/*----------------------------------------------------------------------*/
/* Bob Kline                                       Stream International */
/* bob_kline@stream.com               formerly Corporate Software, Inc. */
/* voice: (703) 522-0820 x-311                      fax: (703) 522-5407 */
/*----------------------------------------------------------------------*/
---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Re: New treatment of 'for (int i ...'
#2473
Author: Steven Correll
Date: Thu, 09 Nov 1995 05:47
34 lines
1781 bytes
What was the rationale for this change, which from here looks quite
gratuitous? It's reminiscent of the old Pascal rule that the value of a
loop index was undefined after the loop exited; that was apparently
motivated by the belief that compilers were too stupid to figure out
on a case-by-case when a value could safely be killed.

The change makes it difficult to write programs that will work in both old
compilers and new ones while implementors scurry to catch up with the
ever-inventive committee. This technique won't work in current compilers:

	for (unsigned i = 0; ...; ...)
	  ...
	for (i = 0; ...; ...)
	  ...

And this won't work in older ones:

	for (unsigned i = 0; ...; ...)
	  ...
	for (unsigned i = 0; ...; ...)
	  ...

Must portable programs do this?

	for (unsigned i0 = 0; ...; ...)
	  ...
	for (unsigned i1 = 0; ...; ...)
	  ...
-- 
Steven Correll == PO Box 66625, Scotts Valley, CA 95067 == sjc@netcom.com
---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Re: New treatment of 'for (int i ...'
#2484
Author: Fergus Henderson
Date: Thu, 09 Nov 1995 07:40
54 lines
2589 bytes
sjc@netcom.com (Steven Correll) writes:

>What was the rationale for this change, which from here looks quite
>gratuitous?

See pages 99-100 of "Design and Evolution of C++".

Basically the reason is that the scope of names should be kept as small
as possible.  The reason that finally persuaded the committee to make
the change was consistency.  The committee added the ability to declare
a variable in an `if' statement, particularly for use with
dynamic_cast:

	if (Foo *foo_p = dynamic_cast<Foo *>(p)) {
		...
	else if (Bar *bar_p = dynamic_cast<Bar *>(p)) {
		...
	} else {
		...
	}

Here the scope of `foo_p' and `bar_p' is only their respective branches
of the if-then-else.  It would be very confusing if there was one rule
for `if' and a different rule for `for'.

>The change makes it difficult to write programs that will work in both old
>compilers and new ones while implementors scurry to catch up with the
>ever-inventive committee.

There is a neat hack which gives you the new behaviour with old compilers:

	#ifdef USE_HACK_FOR_NEW_FOR_SCOPE
	#define for(x) if (0) ; else for(x)
	#endif

(Did I get that right this time?)

I think this hack is Andrew Koenig's idea.  The reason this works is
that there is an implied scope around the statement in the `else' part
of an if-then-else.  (It might not work with really ancient compilers
that don't implement that rule, but probably nothing else will work
with those compilers either.)

So you can just chuck the above hack in a head file, write code as if
your compiler implemented the new rules, and if you are using an old
compiler, compile with `-DUSE_HACK_FOR_NEW_FOR_SCOPE'.

--
Fergus Henderson             	WWW: http://www.cs.mu.oz.au/~fjh
fjh@cs.mu.oz.au              	PGP: finger fjh@128.250.37.3
---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Re: New treatment of 'for (int i ...'
#2487
Author: Robert Buren
Date: Thu, 09 Nov 1995 19:25
53 lines
1993 bytes
Steven Correll wrote:
|> 
|> What was the rationale for this change, which from here looks quite
|> gratuitous? It's reminiscent of the old Pascal rule that the value of a
|> loop index was undefined after the loop exited; that was apparently
|> motivated by the belief that compilers were too stupid to figure out
|> on a case-by-case when a value could safely be killed.
|> 
|> The change makes it difficult to write programs that will work in both old
|> compilers and new ones while implementors scurry to catch up with the
|> ever-inventive committee. This technique won't work in current compilers:
|> 
|>         for (unsigned i = 0; ...; ...)
|>           ...
|>         for (i = 0; ...; ...)
|>           ...
|> 
|> And this won't work in older ones:
|> 
|>         for (unsigned i = 0; ...; ...)
|>           ...
|>         for (unsigned i = 0; ...; ...)
|>           ...
|> 
|> Must portable programs do this?
|> 
|>         for (unsigned i0 = 0; ...; ...)
|>           ...
|>         for (unsigned i1 = 0; ...; ...)
|>           ...

If you really want to write programs for both old and new compilers, what's
wrong with the following?:

  {
  unsigned i;
  for( i = 0; ...; ...)
    ...
  for( i = 0; ...; ...)
    ...
  }

/Robert

-- 
     Robert Buren
     erarobu@era-t.ericsson.se

---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Re: New treatment of 'for (int i ...'
#2489
Author: Alex Martelli
Date: Thu, 09 Nov 1995 19:28
31 lines
1356 bytes
sjc@netcom.com (Steven Correll) writes:
	...
>Must portable programs do this?
>	for (unsigned i0 = 0; ...; ...)
>	  ...
>	for (unsigned i1 = 0; ...; ...)

No,

	unsigned i;
	for (i=0; ...; ...)
	  ...
	for (i=0; ...; ...)
	  ...

has exactly the same semantics as the old rule, so, if you want to
keep portability to older compilers, you can perfectly well use this.


Alex
--
DISCLAIMER: these are TOTALLY personal opinions and viewpoints, NOT connected
in any way with my employer, nor any other organization or individual!
Email: martelli@cadlab.it                            Phone: +39 (51) 597313
CAD.LAB s.p.a., v. Ronzani 7/29, Casalecchio, Italia   Fax: +39 (51) 597120

---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Re: New treatment of 'for (int i ...'
#2491
Author: Mike Ferrel
Date: Fri, 10 Nov 1995 01:12
29 lines
1457 bytes
In article <sjcDHqMKM.MBG@netcom.com>, sjc@netcom.com (Steven Correll) wrote:
> Must portable programs do this?
> 
>         for (unsigned i0 = 0; ...; ...)
>           ...
>         for (unsigned i1 = 0; ...; ...)
>           ...

How about

      unsigned i;
      for(i = 0; ...; ...)
         ...
      for(i = 0; ...; ...)
         ...

This works for all compilers, and is what we all did before we could
declare it in the loop anyway.  I have used it to go back and forth
between CodeWarrior, which implements the new scope, and Borland which
does the old.

-- 
Mike Ferrel
Sonoma State University
mferrel@zippy.sonoma.edu
---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Re: New treatment of 'for (int i ...'
#2503
Author: Dr. Richard Botting
Date: Fri, 10 Nov 1995 05:21
94 lines
4013 bytes
Steven Correll (sjc@netcom.com) wrote:
: What was the rationale for this change, which from here looks quite
: gratuitous? It's reminiscent of the old Pascal rule that the value of a
: loop index was undefined after the loop exited; 

>From within the C mindset it looks counter-intuitive.

It is effectively a return to the FOR loop of Algol 68 and
and a certain language standardized in 1983.  The 1968 form
reflected the informal use bound variables in mathematics
and their use in quantifiers (for all x...) in symbolic logic
and the lambda calculus.

The 1983 motivation was most un-C-like:  It was thought 
that it should lead to fewer bugs.  Experience shows that it is an
occasional pain in the neck, but does eliminate a set of surprises.
Indeed I had a kind of example of this effect, while teaching the
basics of for-loops.  I had a laboratory where the students had to
find my error in the following code
	int i;
	int sum=0
	for( i=1; i<=n; i++);
		sum := i;
	cout<<sum; //produces n+1... why?
Now the tightly bound loop on a standard compiler
	int sum=0;
	for(int i=1; i<=n; i++);
		sum +=i;
	cout <<sum;
will not compile.

Unlike most safety mechanisms it is not difficult to
work around.  However a wise programmer will use a more sophisticated
rule than:
	Make scopes as small as possible.
Perhaps something like:
	Make the scope meaningful
is a better rule.

For example, suppose we have a string of characters and want to
scan across it from start to finish, but treat it as a sequence of
three different iterations then we would write
	{//Start of scan
		char *pointer=string;
		for(; whatever(pointer); pointer++)
			dowhatever(pointer);
		for(; whatever2(pointer); pointer++)
			dowhatever2(pointer);
		for(; whatever3(pointer); pointer++)
			dowhatever3(pointer);
	}//end of scan
because the meaning of pointer is the same - even as its value
changes - throughout the block and across 3 for-loops.

However if we want to do three scans of the same string, one after
another:
		for(char *q=string; whatever(q); q++)
			dowhatever(q);
		for(char *q=string; whatever2(q); q++)
			dowhatever2(q);
		for(char *q=string; whatever3(q); q++)
			dowhatever3(q);
There are clear opportunities for a compiler to optimize
loops like this - because the scopes do not overlap.

One can imagine a combination.... A long scan of the whole
string while we process each part together with three different strings:
		char *p=string;
		for(char*q=start1; whatever(p,q); p++,q++)
			dowhatever(p,q);
		for(char*q=start2; whatever2(p,q); p++,q++)
			dowhatever2(p,q);
		for(char*q=start3; whatever3(p,q); p++,q++)
			dowhatever3(p,q);
This extends to counters, subscripts, indexes, and iterators.

This discipline breaks down, of course, when the meaningful
life of two or more variables do not nest but overlap.  This
is a kind of logical parallelism that is as hard to believe in
as it is to code. (and also off topic!)

--
	dick@csci.csusb.edu=rbotting@wiley.csusb.edu.
Find out what's new at http://www.csci.csusb.edu/doc/www.sites.html
Disclaimer:`CSUSB may or may not agree with this message`.
Copyright(1995):Copy this freely but include the following link to the
<a href="http://www.csci.csusb.edu/dick/signature.html">author's signature</a>


---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Re: New treatment of 'for (int i ...'
#2555
Author: Randy Oxentenko
Date: Mon, 13 Nov 1995 12:39
42 lines
1580 bytes

In article <sjcDHqMKM.MBG@netcom.com>, Steven Correll <sjc@netcom.com> wrote:
>This technique won't work in current compilers:
>
>	for (unsigned i = 0; ...; ...)
>	  ...
>	for (i = 0; ...; ...)
>	  ...
>
>And this won't work in older ones:
>
>	for (unsigned i = 0; ...; ...)
>	  ...
>	for (unsigned i = 0; ...; ...)
>	  ...
>
>Must portable programs do this?
>
>	for (unsigned i0 = 0; ...; ...)
>	  ...
>	for (unsigned i1 = 0; ...; ...)
>	  ...


It is, of course, still permissible in both cases to write this:

	unsigned i;
	for (i = 0; ...; ...)
	  ...
	for (i = 0; ...; ...)
	  ...
-- 
Randy Oxentenko           | It is foolish to criticize.  There is little
rdo@elt.com               | point in fretting over the fact that God has
http://www.dfw.net/~rox/  | not seen fit to distribute evenly the gift
Opinions are not from ELT | of intelligence.           -- John Wanamaker

---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Re: New treatment of 'for (int i ...'
#2550
Author: Phil Richards
Date: Tue, 14 Nov 1995 13:51
41 lines
1773 bytes
In <mferrel-0911951136400001@sa-1en64.sonoma.edu>,
	Mike Ferrel <mferrel@zippy.sonoma.edu> writes:
> In article <sjcDHqMKM.MBG@netcom.com>, sjc@netcom.com (Steven Correll)
> wrote:
> > Must portable programs do this?
> >         for (unsigned i0 = 0; ...; ...)
> >           ...
> >         for (unsigned i1 = 0; ...; ...)
> >           ...
> How about
>       unsigned i;
>       for(i = 0; ...; ...)
>          ...
>       for(i = 0; ...; ...)
>          ...

How about:

	{
	  unsigned i;
	  for (i = 0; ...; ...)
		...
	}
	{
	  unsigned i;
	  for (i = 0; ...; ...)
		...
	}

Gives the advantages of the new style scoping barring an annoying
extra level of indentation and is portable between compilers.  That's
what I've used until now -- the old style led to too many annoying 
problems when rearranging code.

Phil
--
not speaking for ICL
---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Re: New treatment of 'for (int i ...'
#2571
Author: Steven Correll
Date: Tue, 14 Nov 1995 20:32
54 lines
2389 bytes
>In article <sjcDHqMKM.MBG@netcom.com>, Steven Correll <sjc@netcom.com> wrote:
>>This technique won't work in current compilers:
>>
>>	for (unsigned i = 0; ...; ...)
>>	  ...
>>	for (i = 0; ...; ...)
>>	  ...
>>
>>And this won't work in older ones:
>>
>>	for (unsigned i = 0; ...; ...)
>>	  ...
>>	for (unsigned i = 0; ...; ...)
>>	  ...
>>
>>Must portable programs do this?
>>
>>	for (unsigned i0 = 0; ...; ...)
>>	  ...
>>	for (unsigned i1 = 0; ...; ...)
>>	  ...

In article <DHzF5D.DKo@elt.com>, Randy Oxentenko <rdo@elt.com> wrote:
>It is, of course, still permissible in both cases to write this:
>
>	unsigned i;
>	for (i = 0; ...; ...)
>	  ...
>	for (i = 0; ...; ...)
>	  ...

To put an end to the long stream of replies suggesting this: Yes, I realize
one can use an uninitialized local variable. For that matter, one can use an
uninitialized _global_ variable. I assumed the entire point of permitting the
declaration to appear inside the "for" in the first place was to avoid
separating declaration from initialization.

Surely the short-term cost of the change is to make it cumbersome to
initialize a for-loop variable at the point of declaration (because either an
old compiler or a new one is likely to complain, and the macro workaround is
not robust); and the long-term cost is to make it impossible in some cases
(because the value defined inside the loop needs to be referenced after the
loop has terminated). The short- and long-term advantage is to make the
semantics of "for" more consistent with the semantics of "if". De gustibus
non disputandum...
-- 
Steven Correll == PO Box 66625, Scotts Valley, CA 95067 == sjc@netcom.com


---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads