Topic: New treatment of 'for (int i ...
Author: sjc@netcom.com (Steven Correll)
Date: 1995/11/14 Raw View
>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. ]
Author: A.Main@dcs.warwick.ac.uk (Zefram)
Date: 1995/11/16 Raw View
Fergus Henderson <fjh@munta.cs.mu.OZ.AU> wrote:
>mikes@forte.com (Mike Schilling) writes:
>>Fergus Henderson (fjh@munta.cs.mu.OZ.AU) wrote:
>>: 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
>>Try this with:
>>
>> for (i = 0, p = string; *p; i++, p++)
>
>Yes, that macro hack does have its disadvantages.
[convoluted "extra parentheses" solution elided]
The obvious improvement to the kludge is:
#ifdef USE_HACK_FOR_NEW_FOR_SCOPE
#define for if (0) ; else for
#endif
which solves the comma problem completely.
-zefram
---
[ 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. ]
Author: sjc@netcom.com (Steven Correll)
Date: 1995/11/09 Raw View
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. ]
Author: mferrel@zippy.sonoma.edu (Mike Ferrel)
Date: 1995/11/10 Raw View
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. ]
Author: dick@silicon.csci.csusb.edu (Dr. Richard Botting)
Date: 1995/11/10 Raw View
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. ]
Author: mikes@forte.com (Mike Schilling)
Date: 1995/11/11 Raw View
Fergus Henderson (fjh@munta.cs.mu.OZ.AU) wrote:
: 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?)
Try this with:
for (i = 0, p = string; *p; i++, p++)
Mike
---
[ 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. ]
Author: JdeBP@jba.co.uk
Date: 1995/11/11 Raw View
In article <9531318.2076@mulga.cs.mu.OZ.AU> you wrote:
: 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?)
No. (-:
( Hint : you may want to consult the substitution rules for function-like
macros again. )
I've started to use this macro, and I can report that it has one serious
drawback. The compiler spits out reams of useless "a constant was used
as the controlling expression in an if statement" warnings. (-:
Oh yes ... it also tells me that my macro overrides the keyword "for".
I wish I was allowed to use the compiler that has the facility to
selectively disable warnings ...
---
[ 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. ]
Author: fjh@munta.cs.mu.OZ.AU (Fergus Henderson)
Date: 1995/11/11 Raw View
mikes@forte.com (Mike Schilling) writes:
>Fergus Henderson (fjh@munta.cs.mu.OZ.AU) wrote:
>: 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?)
>Try this with:
>
> for (i = 0, p = string; *p; i++, p++)
Yes, that macro hack does have its disadvantages.
In cases like this, you can use some extra parentheses:
for ((i = 0, p = string); *p; (i++, p++))
For cases like
for (int i = 0, j = 0; a[i] != a[j]; i++, j++)
^^^
it's a bit trickier - you have to write something like
int i = 0, j = 0;
for (; a[i] != a[j]; (i++, j++))
or
int i, j;
for (i = j = 0; a[i] != a[j]; (i++, j++))
--
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. ]
Author: rdo@elt.com (Randy Oxentenko)
Date: 1995/11/13 Raw View
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. ]