By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
440,092 Members | 1,597 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 440,092 IT Pros & Developers. It's quick & easy.

How not to abuse a "for loop": examples?

P: n/a
At the page:
http://www.strath.ac.uk/IT/Docs/Ccou...00000000000000
or
http://tinyurl.com/4ptzs

the author warns:
"The for loop is frequently used, usually where the loop will be
traversed a fixed number of times. It is very flexible, and novice
programmers should take care not to abuse the power it offers."

Could someone give an example of this abuse? I'm googling for
c misuse "for loop"
c abuse "for loop"
with little luck.

I'd like to see what *not* to do :)

Toby
Nov 14 '05 #1
Share this Question
Share on Google+
32 Replies


P: n/a
On 9 Aug 2004, Toby Newman wrote:
the author warns:
"The for loop is frequently used, usually where the loop will be
traversed a fixed number of times. It is very flexible, and novice
programmers should take care not to abuse the power it offers."

Could someone give an example of this abuse? I'm googling for
c misuse "for loop"
c abuse "for loop"
with little luck.

I'd like to see what *not* to do :)


for (a(), b(), c(), d(), e(), f(), g();
h(), i(), j(), k(), l(), m(), n(), o(), p();
q(), r(), s(), t(), u(), v(), w(), x(), y(), z())
;

Tak-Shing

Nov 14 '05 #2

P: n/a
"Toby Newman" <go****@asktoby.com> wrote in message
news:25**************************@posting.google.c om...

"The for loop is frequently used, usually where the loop will be
traversed a fixed number of times. It is very flexible, and novice
programmers should take care not to abuse the power it offers."

Could someone give an example of this abuse? I'm googling for
c misuse "for loop"
c abuse "for loop"
with little luck.

I'd like to see what *not* to do :)


for (i = 0; i < 100; i += (i == 98) ? -97 : 2)

for (; *++argv
&& (fp = fopen(*argv, "rb"))
&& fread(buffer, 10, 10, fp) == 10
&& fclose(fp) != EOF; )

Although, I'm guilty of both. ;)

--
Peter
Nov 14 '05 #3

P: n/a
Toby Newman wrote:
At the page:
http://www.strath.ac.uk/IT/Docs/Ccou...00000000000000
or
http://tinyurl.com/4ptzs

the author warns:
"The for loop is frequently used, usually where the loop will be
traversed a fixed number of times. It is very flexible, and novice
programmers should take care not to abuse the power it offers."

Could someone give an example of this abuse? I'm googling for
c misuse "for loop"
c abuse "for loop"
with little luck.

I'd like to see what *not* to do :)

Toby


for (i = 0; i < 100; ++i)
{
--i;
}

float j;
for (j = 0.0; j != 10.0; j += 0.1)
{
}

unsigned int m;
for (m = 9; m > 0; m -= 2)
{
}

--
Thomas Matthews

C++ newsgroup welcome message:
http://www.slack.net/~shiva/welcome.txt
C++ Faq: http://www.parashift.com/c++-faq-lite
C Faq: http://www.eskimo.com/~scs/c-faq/top.html
alt.comp.lang.learn.c-c++ faq:
http://www.comeaucomputing.com/learn/faq/
Other sites:
http://www.josuttis.com -- C++ STL Library book

Nov 14 '05 #4

P: n/a
On Mon, 9 Aug 2004, Toby Newman wrote:
At the page:
http://www.strath.ac.uk/IT/Docs/Ccou...00000000000000
or
http://tinyurl.com/4ptzs

the author warns:
"The for loop is frequently used, usually where the loop will be
traversed a fixed number of times. It is very flexible, and novice
programmers should take care not to abuse the power it offers."

Could someone give an example of this abuse? I'm googling for
c misuse "for loop"
c abuse "for loop"
with little luck.

I'd like to see what *not* to do :)


There is nothing you can do with the for loop that you cannot do with the
while loop. For some bizzare reason, people tend to abuse the comma
operator in a for loop but not in a while loop. The for loop has three
sections:

for(init; check; incr)

The init section is where you initialize variables used in the for loop. A
little abuse happens here. People initialize a number of variables here
when they could have been initialized before the loop. I like to do this
if the variables are relative to the loop. If I initialize them at the top
of scope the initialization might not be visible while I step through the
for loop.

The big abuse is in the check section. Here you should be checking to see
if the for loop should exit of not. Some times programmers will stick a
number of statements that could just as easily fit in the body of the loop
into this section. This often makes for a hard to read bit of code.

Another place for abuse is the incr section. This is the section that you
should be incrementing something. If you use a for loop for stepping
through a known number of iterations then this section should just be
incrementing the counter used to keep track of the iterations.

There are no hard and fast rules on this. I often see:

while((c = getchar()) != EOF) {
/* code */
}

getting converted to:

for(; (c = getchar()) != EOF; /* code */);

It is all a matter of coding conventions or style.

--
Send e-mail to: darrell at cs dot toronto dot edu
Don't send e-mail to vi************@whitehouse.gov
Nov 14 '05 #5

P: n/a
In article <25**************************@posting.google.com >,
Toby Newman <go****@asktoby.com> wrote:
At the page:
http://www.strath.ac.uk/IT/Docs/Ccou...00000000000000
or
http://tinyurl.com/4ptzs

the author warns:
"The for loop is frequently used, usually where the loop will be
traversed a fixed number of times. It is very flexible, and novice
programmers should take care not to abuse the power it offers."

Could someone give an example of this abuse? I'm googling for
c misuse "for loop"
c abuse "for loop"
with little luck.

I'd like to see what *not* to do :)


--------
for(in=fopen(filename,"r");in&&fgets(buf,sizeof buf,in);)
{
/*do stuff with this line of the file*/
}
--------
/*i is unsigned*/
for(i=1;i;i*=2)
{
/*do stuff with this power of 2*/
}
/*we fall out when we hit max(i)+1 and the unsigned arithmetic wraps
back around to 0
*/
--------
A favorite of mine, that falls under "uncommon" but not "abuse", is:
--------
for(curr=head;curr;curr=curr->next)
{
/*Do stuff with this list node*/
}
--------
to walk through a linked list.
dave

--
Dave Vandervies dj******@csclub.uwaterloo.ca
[This] is otherwise known as 'learning by experience'. I don't often
come across people who publicly state they're not interested in that.
--Arthur van der Harg in the scary devil monastery
Nov 14 '05 #6

P: n/a
Dave Vandervies wrote:
A favorite of mine, that falls under "uncommon" but not "abuse", is:
--------
for(curr=head;curr;curr=curr->next)
{
/*Do stuff with this list node*/
}
--------
to walk through a linked list.


Is that really so uncommon? It seems like the natural way to traverse a
linked list. (Except that I would explicitly test for curr != NULL, since
curr is not a boolean value. But that's also a matter of taste).
Christian
Nov 14 '05 #7

P: n/a
"Christian Kandeler" <ch****************@hob.de> wrote in message
news:2n************@uni-berlin.de...
Dave Vandervies wrote:
A favorite of mine, that falls under "uncommon" but not "abuse", is:
--------
for(curr=head;curr;curr=curr->next)
{
/*Do stuff with this list node*/
}
--------
to walk through a linked list.


Is that really so uncommon? It seems like the natural way to traverse a
linked list. (Except that I would explicitly test for curr != NULL, since
curr is not a boolean value. But that's also a matter of taste).


curr != NULL or curr != 0?
I'm confused now, after the Null Pointer thread... "Keith!!! Where are
you?!!"

--
Mabden
Nov 14 '05 #8

P: n/a
Mabden wrote:

"Christian Kandeler" <ch****************@hob.de> wrote in message
news:2n************@uni-berlin.de...
Dave Vandervies wrote:
for(curr=head;curr;curr=curr->next)
(Except that I would explicitly test for curr != NULL, since
curr is not a boolean value. But that's also a matter of taste).


curr != NULL or curr != 0?


Since the point of writing curr != NULL or curr != 0
instead of just (;curr;) is to enhance legibility,
I think it makes sense to write curr != NULL
When I read (curr != NULL), that tells me that the author
thought that curr was a pointer, when he wrote the code.
Nov 14 '05 #9

P: n/a
go****@asktoby.com (Toby Newman) wrote in message news:<25**************************@posting.google. com>...
"The for loop is ... very flexible, and novice
programmers should take care not to abuse the power it offers."

Could someone give an example of this abuse? ...
I'd like to see what *not* to do :)


http://tinyurl.com/2452h/wnim.htm
(scroll about half way down.)

Hope this helps,
James
Nov 14 '05 #10

P: n/a
boa
James Dow Allen wrote:
go****@asktoby.com (Toby Newman) wrote in message news:<25**************************@posting.google. com>...
"The for loop is ... very flexible, and novice
programmers should take care not to abuse the power it offers."

Could someone give an example of this abuse? ...
I'd like to see what *not* to do :)

http://tinyurl.com/2452h/wnim.htm
(scroll about half way down.)

Hope this helps,
James


You win. ;-)

Why did you write it like that?

boa
Nov 14 '05 #11

P: n/a
On 9 Aug 2004 01:03:16 -0700, go****@asktoby.com (Toby Newman) wrote:
At the page:
http://www.strath.ac.uk/IT/Docs/Ccou...00000000000000
or
http://tinyurl.com/4ptzs

the author warns:
"The for loop is frequently used, usually where the loop will be
traversed a fixed number of times. It is very flexible, and novice
programmers should take care not to abuse the power it offers."

Could someone give an example of this abuse? I'm googling for
c misuse "for loop"
c abuse "for loop"
with little luck.

I'd like to see what *not* to do :)

Toby


Something like this?

for(i=0; i<1000; ++i)
for(j=0; j<1000; ++j)
for(k=0; k<1000; ++k)
for(ii=0; ii<1000; ++ii)
for(jj=0; jj<1000; ++jj)
for(kk=0; kk<1000; ++kk)
for(z=0; z<1000; ++z)
f(i,j,k,ii, jj, kk, z);
Nov 14 '05 #12

P: n/a
# Thomas Matthews
for (i = 0; i < 100; ++i)
{
--i;
}
Gets the program stuck in a loop. I guess you could do the same with
while(1)
{}
float j;
for (j = 0.0; j != 10.0; j += 0.1)
{
}
Keeps the program occupied for a little while. I guess better to time
the pause some other way, more accurately and less dependant upon
processor speed.
unsigned int m;
for (m = 9; m > 0; m -= 2)
{
}


I guess the problem with this one is that m being an unsigned integer
will cause problems when you perform
9 - 2 - 2 - 2 - 2 - 2...
and never get to be lessthan or equal to 0, so the loop goes on forever.
--
Toby
Nov 14 '05 #13

P: n/a
# James Dow Allen
go****@asktoby.com (Toby Newman) wrote in message news:<25**************************@posting.google. com>...
"The for loop is ... very flexible, and novice
programmers should take care not to abuse the power it offers."

Could someone give an example of this abuse? ...
I'd like to see what *not* to do :)


http://tinyurl.com/2452h/wnim.htm
(scroll about half way down.)

Hope this helps,
James


This bit?

for (numpile = 1; numpile <= plast; numpile++)
for (numrem = 1; numrem <= psize[plast]; numrem++)
if (WINNER)
goto contin_3;

He's nesting them. That's frowned upon?

--
Toby
Nov 14 '05 #14

P: n/a
boa
Toby Newman wrote:
# James Dow Allen
go****@asktoby.com (Toby Newman) wrote in message news:<25**************************@posting.google. com>...
"The for loop is ... very flexible, and novice
programmers should take care not to abuse the power it offers."

Could someone give an example of this abuse? ...
I'd like to see what *not* to do :)


http://tinyurl.com/2452h/wnim.htm
(scroll about half way down.)

Hope this helps,
James

This bit?

for (numpile = 1; numpile <= plast; numpile++)
for (numrem = 1; numrem <= psize[plast]; numrem++)
if (WINNER)
goto contin_3;

He's nesting them. That's frowned upon?


Did you miss the definition of the NFOR macro? Worry not, here's a copy.

#define NFOR(N) \
for (psize[N] = 0; \
psize[N] <= psize[N-1] \
&& (N > NROW - 2 || N == NROW - 2 && \
(winbits = (unsigned short *)(*grow[N-1]++ \
= calloc(1, WID * sizeof (unsigned short)))) \
|| (grow[N] = (Node *)(*grow[N-1]++ \
= calloc(1, ((unsigned)psize[N]+1) \
* sizeof (Node))))); psize[N]++, plast = N)
And note how it is used:
/*
* After the foregoing preliminaries, a brief nested
* loop suffices to solve every position.
*/
NFOR(1) NFOR(2) NFOR(3) NFOR(4) NFOR(5) NFOR(6)
NFOR(7) NFOR(8) NFOR(9) NFOR(10) NFOR(11) NFOR(12) {
if (plast) {
for (numpile = 1; numpile <= plast; numpile++)
for (numrem = 1; numrem <= psize[plast]; numrem++)
if (WINNER)
goto contin_3;
winbits[INDX(10)] |= 1 << INDX(11);
contin_3: ;
}
}

I tried to preprocess (gcc -E -P) and indent it to be able to post it,
but that wasn't possible with 14 nested for loops and a couple of
if-tests as well. Clearly a winner, IMHO <g>

boa@home

Nov 14 '05 #15

P: n/a
# boa
Toby Newman wrote:
# James Dow Allen
go****@asktoby.com (Toby Newman) wrote in message news:<25**************************@posting.google. com>...

"The for loop is ... very flexible, and novice
programmers should take care not to abuse the power it offers."

Could someone give an example of this abuse? ...
I'd like to see what *not* to do :)

http://tinyurl.com/2452h/wnim.htm
(scroll about half way down.)

Hope this helps,
James

This bit?

for (numpile = 1; numpile <= plast; numpile++)
for (numrem = 1; numrem <= psize[plast]; numrem++)
if (WINNER)
goto contin_3;

He's nesting them. That's frowned upon?


Did you miss the definition of the NFOR macro? Worry not, here's a copy.

#define NFOR(N) \
for (psize[N] = 0; \
psize[N] <= psize[N-1] \
&& (N > NROW - 2 || N == NROW - 2 && \
(winbits = (unsigned short *)(*grow[N-1]++ \
= calloc(1, WID * sizeof (unsigned short)))) \
|| (grow[N] = (Node *)(*grow[N-1]++ \
= calloc(1, ((unsigned)psize[N]+1) \
* sizeof (Node))))); psize[N]++, plast = N)
And note how it is used:
/*
* After the foregoing preliminaries, a brief nested
* loop suffices to solve every position.
*/
NFOR(1) NFOR(2) NFOR(3) NFOR(4) NFOR(5) NFOR(6)
NFOR(7) NFOR(8) NFOR(9) NFOR(10) NFOR(11) NFOR(12) {
if (plast) {
for (numpile = 1; numpile <= plast; numpile++)
for (numrem = 1; numrem <= psize[plast]; numrem++)
if (WINNER)
goto contin_3;
winbits[INDX(10)] |= 1 << INDX(11);
contin_3: ;
}
}

I tried to preprocess (gcc -E -P) and indent it to be able to post it,
but that wasn't possible with 14 nested for loops and a couple of
if-tests as well. Clearly a winner, IMHO <g>

boa@home


So, do I understand correctly that the extreme nesting of for loops is
bad behaviour because it makes the code hard to read and hard for pre-
processors to parse?

--
Toby
Nov 14 '05 #16

P: n/a
boa
Toby Newman wrote:
# boa
Toby Newman wrote:

# James Dow Allen
go****@asktoby.com (Toby Newman) wrote in message news:<25**************************@posting.google. com>...
>"The for loop is ... very flexible, and novice
>programmers should take care not to abuse the power it offers."
>
>Could someone give an example of this abuse? ...
>I'd like to see what *not* to do :)

http://tinyurl.com/2452h/wnim.htm
(scroll about half way down.)

Hope this helps,
James

This bit?

for (numpile = 1; numpile <= plast; numpile++)
for (numrem = 1; numrem <= psize[plast]; numrem++)
if (WINNER)
goto contin_3;

He's nesting them. That's frowned upon?

Did you miss the definition of the NFOR macro? Worry not, here's a copy.

#define NFOR(N) \
for (psize[N] = 0; \
psize[N] <= psize[N-1] \
&& (N > NROW - 2 || N == NROW - 2 && \
(winbits = (unsigned short *)(*grow[N-1]++ \
= calloc(1, WID * sizeof (unsigned short)))) \
|| (grow[N] = (Node *)(*grow[N-1]++ \
= calloc(1, ((unsigned)psize[N]+1) \
* sizeof (Node))))); psize[N]++, plast = N)
And note how it is used:
/*
* After the foregoing preliminaries, a brief nested
* loop suffices to solve every position.
*/
NFOR(1) NFOR(2) NFOR(3) NFOR(4) NFOR(5) NFOR(6)
NFOR(7) NFOR(8) NFOR(9) NFOR(10) NFOR(11) NFOR(12) {
if (plast) {
for (numpile = 1; numpile <= plast; numpile++)
for (numrem = 1; numrem <= psize[plast]; numrem++)
if (WINNER)
goto contin_3;
winbits[INDX(10)] |= 1 << INDX(11);
contin_3: ;
}
}

I tried to preprocess (gcc -E -P) and indent it to be able to post it,
but that wasn't possible with 14 nested for loops and a couple of
if-tests as well. Clearly a winner, IMHO <g>

boa@home

So, do I understand correctly that the extreme nesting of for loops is
bad behaviour because it makes the code hard to read


IMO, yes.
and hard for pre-processors to parse?


That was probably just bad english by me. The preprocessor had no
problems processing the code at all, but the preprocessed code was
unreadable (at least to me).

boa@home
Nov 14 '05 #17

P: n/a
In article <2n************@uni-berlin.de>,
Christian Kandeler <ch****************@hob.de> wrote:
Dave Vandervies wrote:
A favorite of mine, that falls under "uncommon" but not "abuse", is:
--------
for(curr=head;curr;curr=curr->next)
{
/*Do stuff with this list node*/
}
--------
to walk through a linked list.


Is that really so uncommon? It seems like the natural way to traverse a
linked list.


Most linked list traversals I've seen use while instead:
--------
curr=head;
while(curr)
{
/*do stuff*/
curr=curr->next;
}
--------
I suspect that this may be a result of most languages having less general
for loops that are only suitable for counting, so most programmers don't
come up with it on their own. (I don't think I came up with it on my own,
but I have no idea where I first encountered it.)
dave

--
Dave Vandervies dj******@csclub.uwaterloo.ca
If depends on the compiler and the hardware. But in general, the
first will be incredibly fast while the other will be incredibly
fast. --Gergo Barany in comp.lang.c
Nov 14 '05 #18

P: n/a

On Tue, 10 Aug 2004, Toby Newman wrote:

# Thomas Matthews
for (i = 0; i < 100; ++i)
{
--i;
}


Gets the program stuck in a loop. I guess you could do the same with
while(1) {}


Correct. However, I'm not sure if Thomas was also meaning to
refer to the more common but IMHO equally abusive

for (i=0; i < 100; ++i) {
if (foo(i)) {
/* You know what? Let's process this |i| again. */
--i; continue;
}
}

However, just because it's abusive doesn't necessarily mean you
should never do it. ;)
float j;
for (j = 0.0; j != 10.0; j += 0.1)
{
}


Keeps the program occupied for a little while. I guess better to time
the pause some other way, more accurately and less dependant upon
processor speed.


You missed the point. Google up "comp.lang.c FAQ" and read
Section 14, which is all about floating-point numbers. (In a
nutshell: 'j' may never be equal to 10.0, due to rounding errors
in the addition operations.)
unsigned int m;
for (m = 9; m > 0; m -= 2)
{
}


I guess the problem with this one is that m being an unsigned integer
will cause problems when you perform
9 - 2 - 2 - 2 - 2 - 2...
and never get to be lessthan or equal to 0, so the loop goes on forever.


Correct. But note that somebody else already posted abusive but
possibly useful code that looked something like this:

unsigned m;
for (m = 9; m > 0; m -= 2) {
if (m > 9) m = 8;
foo(m);
}

I didn't see any FAQ about unsigned arithmetic, but here's something
just as good:
http://www.eskimo.com/~scs/cclass/int/sx4ca.html

HTH,
-Arthur
Nov 14 '05 #19

P: n/a
jd*********@yahoo.com (James Dow Allen) wrote:
go****@asktoby.com (Toby Newman) wrote:
"The for loop is ... very flexible, and novice
programmers should take care not to abuse the power it offers."

Could someone give an example of this abuse? ...
I'd like to see what *not* to do :)
http://tinyurl.com/2452h/wnim.htm
(scroll about half way down.)


If that page is meant to be a troll then ignore this, but why didn't
you malloc the whole array in one go? This would have saved
screeds of memory and code complexity (although I suppose if you had
then you would have been unable to contribute to this thread).
Quoting from your page:
char Posvalue[13][13][13][13][13][13][13][13][13][13][13][13];

When I try to compile the above statement with FSF's C compiler
I get:
bonzo.c:1: size of array `Posvalue' is too large


typedef char Nodes[13][13][13][13][13][13][13][13][13][13][13][13];
Nodes *Posvalue = calloc(1, sizeof *Posvalue);
Nov 14 '05 #20

P: n/a
>jd*********@yahoo.com (James Dow Allen) wrote:
http://tinyurl.com/2452h/wnim.htm
(scroll about half way down.)

In article <84**************************@posting.google.com >
Old Wolf <ol*****@inspire.net.nz> writes:If that page is meant to be a troll then ignore this, but why didn't
you malloc the whole array in one go?
It will will not fit. (It seems to me that he uses a series of sparse
arrays, coded rather oddly; but I only glanced at the code.)
Quoting from your page:
char Posvalue[13][13][13][13][13][13][13][13][13][13][13][13];

When I try to compile the above statement with FSF's C compiler
I get:
bonzo.c:1: size of array `Posvalue' is too large


typedef char Nodes[13][13][13][13][13][13][13][13][13][13][13][13];
Nodes *Posvalue = calloc(1, sizeof *Posvalue);


This requires pow(13,12) (23 298 085 122 481) bytes -- requiring
about 45 bits' worth of address space (log2(above) is 44.405...).
Not a problem on some modern 64-bit architectures, perhaps, but
most machines have a bit of trouble handing out over 21 thousand
gigabytes (21.7 TB) of virtual memory. :-)
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (4039.22'N, 11150.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 14 '05 #21

P: n/a
# Arthur J. O'Dwyer
float j;
for (j = 0.0; j != 10.0; j += 0.1)
{
}


Keeps the program occupied for a little while. I guess better to time
the pause some other way, more accurately and less dependant upon
processor speed.


You missed the point. Google up "comp.lang.c FAQ" and read
Section 14, which is all about floating-point numbers. (In a
nutshell: 'j' may never be equal to 10.0, due to rounding errors
in the addition operations.)


Thanks for the helpful post. I am aware of the existance of float
rounding errors, but no so aware that I'm able to spot them in the wild
yet :)

So, the code would be corrected by instead doing:

float j;
for (j = 0.0; j < 10.0; j += 0.1)
{
}

--
Toby
Nov 14 '05 #22

P: n/a
Toby Newman wrote:

# Arthur J. O'Dwyer
> float j;
> for (j = 0.0; j != 10.0; j += 0.1)
So, the code would be corrected by instead doing:

float j;
for (j = 0.0; j < 10.0; j += 0.1)


Yes.
Nov 14 '05 #23

P: n/a
Toby Newman wrote:
# Arthur J. O'Dwyer
float j;
for (j = 0.0; j != 10.0; j += 0.1)
{
}

Keeps the program occupied for a little while. I guess better
to time the pause some other way, more accurately and less
dependant upon processor speed.


You missed the point. Google up "comp.lang.c FAQ" and read
Section 14, which is all about floating-point numbers. (In a
nutshell: 'j' may never be equal to 10.0, due to rounding
errors in the addition operations.)


Thanks for the helpful post. I am aware of the existance of
float rounding errors, but no so aware that I'm able to spot
them in the wild yet :)

So, the code would be corrected by instead doing:

float j;
for (j = 0.0; j < 10.0; j += 0.1)
{
}


No, by writing:

int i;
float j;

for (i = 0; i < 100; i++) {
j = i / 10.0;
...
}

--
"Churchill and Bush can both be considered wartime leaders, just
as Secretariat and Mr Ed were both horses." - James Rhodes.
"A man who is right every time is not likely to do very much."
- Francis Crick, co-discover of DNA
Nov 14 '05 #24

P: n/a

On Wed, 11 Aug 2004, pete wrote:
Toby Newman wrote:

# Arthur J. O'Dwyer
> float j;
> for (j = 0.0; j != 10.0; j += 0.1)

So, the code would be corrected by instead doing:

float j;
for (j = 0.0; j < 10.0; j += 0.1)


Yes.


No. CBFalconer has it right, in his parallel reply. Toby's
loop has the exact same problem as the original: you don't know
how many times the loop will be executed! Consider two systems
on which this code might be run; on the first,

j <-- 0, 0.1, 0.2, 0.3, 0.4, 0.499, 0.599, 0.699, 0.799, 0.899, 0.999
(eleven iterations)

On the second,

j <-- 0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9
(ten iterations)

Unless you're actually using this loop to distinguish different
systems according to such icky floating-point behavior, it's better
to stick to comparing integers for equality.

HTH,
-Arthur

Nov 14 '05 #25

P: n/a
Toby Newman wrote:
# Thomas Matthews

for (i = 0; i < 100; ++i)
{
--i;
}

Gets the program stuck in a loop. I guess you could do the same with
while(1)
{}

No. The point is that the index variable is modified
within the block of statements. This was _not_ designed
as a forever loop.


float j;
for (j = 0.0; j != 10.0; j += 0.1)
{
}

Keeps the program occupied for a little while. I guess better to time
the pause some other way, more accurately and less dependant upon
processor speed.

Nope. The point here is that floating point arithmetic
and comparison are not exact enough for this loop. One
should not use floating point values for indices in a
loop.


unsigned int m;
for (m = 9; m > 0; m -= 2)
{
}

I guess the problem with this one is that m being an unsigned integer
will cause problems when you perform
9 - 2 - 2 - 2 - 2 - 2...
and never get to be lessthan or equal to 0, so the loop goes on forever.

This is another issue on unspecified behavior.
The loop causes an underflow at m == 1. One cannot
subract the value of "2" from "1" when the domain
is restricted to all positive integers (including
zero). This is undefined in terms of mathematics.

--
Thomas Matthews

C++ newsgroup welcome message:
http://www.slack.net/~shiva/welcome.txt
C++ Faq: http://www.parashift.com/c++-faq-lite
C Faq: http://www.eskimo.com/~scs/c-faq/top.html
alt.comp.lang.learn.c-c++ faq:
http://www.comeaucomputing.com/learn/faq/
Other sites:
http://www.josuttis.com -- C++ STL Library book

Nov 14 '05 #26

P: n/a
In article <pR****************@newssvr19.news.prodigy.com>,
Thomas Matthews <Th**************************@sbcglobal.net> wrote:
Toby Newman wrote:
# Thomas Matthews
unsigned int m;
for (m = 9; m > 0; m -= 2)
{
}

I guess the problem with this one is that m being an unsigned integer
will cause problems when you perform
9 - 2 - 2 - 2 - 2 - 2...
and never get to be lessthan or equal to 0, so the loop goes on forever.

This is another issue on unspecified behavior.
The loop causes an underflow at m == 1. One cannot
subract the value of "2" from "1" when the domain
is restricted to all positive integers (including
zero). This is undefined in terms of mathematics.


Except that we're talking in terms of C here, not mathematics, and in
C this one is well-defined. Unsigned arithmetic wraps -1 around to
UINT_MAX, which (if I'm not mistaken) is required to be odd, so you get
an infinite loop repeatedly counting down the odd integers in the range
of unsigned int.
dave

--
Dave Vandervies dj******@csclub.uwaterloo.ca
OK, then, call it something else. Let's say flog() to remind me what
should happen to me when I make silly mistakes like that.
--Peter "Shaggy" Haywood in comp.lang.c
Nov 14 '05 #27

P: n/a
Arthur J. O'Dwyer wrote:

On Wed, 11 Aug 2004, pete wrote:
Toby Newman wrote:

# Arthur J. O'Dwyer
>> float j;
>> for (j = 0.0; j != 10.0; j += 0.1)

So, the code would be corrected by instead doing:

float j;
for (j = 0.0; j < 10.0; j += 0.1)


Yes.


No. CBFalconer has it right, in his parallel reply. Toby's
loop has the exact same problem as the original: you don't know
how many times the loop will be executed!


No! Your code has the problem. You don't know whether
or not j will be less than 10.0 in the body of the loop.

link -> data = log(10.0 - j);
}
link -> next = NULL;
Nov 14 '05 #28

P: n/a

On Thu, 12 Aug 2004, pete wrote:

Arthur J. O'Dwyer wrote:
On Wed, 11 Aug 2004, pete wrote:
Toby Newman wrote:
# Arthur J. O'Dwyer
>>> float j;
>>> for (j = 0.0; j != 10.0; j += 0.1)

So, the code would be corrected by instead doing:

float j;
for (j = 0.0; j < 10.0; j += 0.1)

Yes.
No. CBFalconer has it right, in his parallel reply. Toby's
loop has the exact same problem as the original: you don't know
how many times the loop will be executed!


No! Your code has the problem. You don't know whether
or not j will be less than 10.0 in the body of the loop.

link -> data = log(10.0 - j);
}
link -> next = NULL;


I think we've gotten attributions garbled somewhere here.
Thomas's intentionally-wrong code was:
>>> float j;
>>> for (j = 0.0; j != 10.0; j += 0.1)
This is wrong, wrong, wrong.

Your "corrected" version was:
float j;
for (j = 0.0; j < 10.0; j += 0.1)


This is at least a finite loop, but its behavior is still
implementation-defined.

CBFalconer in a parallel subthread suggested
int jj;
for (jj = 0; jj < 100; jj += 1) {
double j = jj / 10.0;


This is absolutely correct and unimpeachable, and there is
absolutely nothing wrong with it. According to me, that is.
Notice that /I/ never wrote any code in this thread. I just
pointed out that /your/ code was wrong, and /Chuck's/ code
was correct. And I stand by that.

I think you may have assumed that Thomas's code was really
CBFalconer's. Now that you know it's not, are you still
argumentative? ;)

-Arthur
Nov 14 '05 #29

P: n/a
Chris Torek <no****@torek.net> wrote:
Old Wolf <ol*****@inspire.net.nz> writes:
If that page is meant to be a troll then ignore this, but why didn't
you malloc the whole array in one go? typedef char Nodes[13][13][13][13][13][13][13][13][13][13][13][13];
Nodes *Posvalue = calloc(1, sizeof *Posvalue);


This requires pow(13,12) (23 298 085 122 481) bytes -- requiring
about 45 bits' worth of address space (log2(above) is 44.405...).
Not a problem on some modern 64-bit architectures, perhaps, but
most machines have a bit of trouble handing out over 21 thousand
gigabytes (21.7 TB) of virtual memory. :-)


Good point. However I have seen Dan Pop recommend this technique
and the OS should optimise sparse arrays by not reserving the space
until it is actually used. Speaking of Mr Pop, I haven't seen any
posts from him for a while.. what's up?
Nov 14 '05 #30

P: n/a


Old Wolf wrote:
Chris Torek <no****@torek.net> wrote:
Old Wolf <ol*****@inspire.net.nz> writes:
If that page is meant to be a troll then ignore this, but why didn't
you malloc the whole array in one go?
typedef char Nodes[13][13][13][13][13][13][13][13][13][13][13][13];
Nodes *Posvalue = calloc(1, sizeof *Posvalue);


This requires pow(13,12) (23 298 085 122 481) bytes -- requiring
about 45 bits' worth of address space (log2(above) is 44.405...).
Not a problem on some modern 64-bit architectures, perhaps, but
most machines have a bit of trouble handing out over 21 thousand
gigabytes (21.7 TB) of virtual memory. :-)

Good point. However I have seen Dan Pop recommend this technique
and the OS should optimise sparse arrays by not reserving the space
until it is actually used. Speaking of Mr Pop, I haven't seen any
posts from him for a while.. what's up?


Isn't this the big vacation season in Europe ... where everybody goes
to a health spa, to prepare themselves to face the coming Christmas
season?

--
Ron Collins
Air Defense/RTSC/BCS
"I have a plan so cunning, you could put a tail on it and call it a weasel"

Nov 14 '05 #31

P: n/a
> >jd*********@yahoo.com (James Dow Allen) wrote:
http://tinyurl.com/2452h/wnim.htm

Putting this piece of code in context, here's the very
first sentence of my lesson9.htm: Programming loses much of its fun when one's
programs all look the same.
Chris Torek <no****@torek.net> wrote in message news:<cf********@news2.newsguy.com>... ... a series of sparse arrays, coded rather oddly ...
Given the above context, I'll take this as a compliment! :-)

The 90-line source program in question is *much harder* to
read or understand than the average 90-line source program.
But that's not a fair comparison. The question should be,
how does the net readability of my code compare with another
program that *solves the same problem*?

I posted the link to this peculiar code almost as a
joke, but now it occurs to me that it might pose an
interesting challenge for programmers in general, or
c.l.c'ers in particular. It would be instructive for
me, and perhaps others, to compare with a properly
coded version, but we'll need that properly coded version.
(It should be a full program that solves Waldo's Nim;
otherwise I'm afraid fragments will be posted that simply
can't accomplish what the peculiar code does.)

Write the program the way it should be; let c.l.c'ers
vote on the best solution. I'll be happy to post the
winning submission at my website (unless the winner feels
this would be a booby prize. :-) It shouldn't take long
to do it: as Mr. Torek pointed out, the peculiar part
just sets up a sparse array, and the rest is a very
simple algorithm which isn't the issue. (A heuristic
improvement may exist, but that would be a separate
topic for alt.brain.teasers.)

A thread based on such a ``contest,'' might be fun for
c.l.c, and you should be grateful to me for playing the
buffoon whose code needs improvement. But first, let me
summarize my feelings about my own code:
(1) it was written for play not pay; paid code would
have been improved in some ways (though I'm afraid
it still would have used a macro like NFOR).
(2) nesting 12 loops seems like the natural and best
way to write the program; since the loops are essentially
identical, using a macro seemed right; with
these decisions, packing the calloc() into the for-statement
substantially simplified the syntax. You may disapprove,
but the intent was to clarify the code, not obfuscate it!
(3) some aspects of the code others find ``bad'' are
indeed bad. My question is whether the cure would
be worse than the disease. We all agree global variables
are bad, but we use them when the alternative is
dozens of unwieldy function arguments. We all agree
long functions are bad, but some of us use them when
factorings aren't really helpful. And I'd like to see the
"proper" version of this program before agreeing it's better.
(4) coding involves trade-offs, and shouldn't be dictated
by dogma. (as an extreme example of dogma, one can find old
messages in c.l.c with the claim that *longjmp()* is
better than *goto* because it's a function, not an (evil)
keyword.)
(5) as most readers realized, the code indulged a whimsical
(or perverse) love of minimalism. I hope some of you also
find programming *Fun*!

* * * * * * * * * * * * * * *

Someone wrote, in effect: Was this a troll?
Just do calloc(13*13*13*13*13*13, 13*13*13*13*13*13); [I've rearranged the 13's so the numbers fit size_t.]

Errh, my contest offer is sincere, but submissions will
be expected to compile and execute on present-day computers.

Someone else wrote, in effect: The flaw in this code is the 18 tab characters `indent'
needs to add, after `cc -E' ...
Was *this* a troll? I personally see nothing wrong with
nesting a dozen loops, especially here when the loops are
equivalent (just handling different axes of a multi-dimensional
structure), but if there *is* something wrong with it,
fitting tabs onto paper or screen can't be the problem, can
it? And why would anyone think adding 18 indentations to
the code is a good idea (unless your 4th grade programming
teacher used to hit you with a ruler when you didn't indent
every sub-block)? Finally, although we've all used
cc -E | indent
to decipher obfuscated code, the idea that code like

#define NFOR(N) something_very_complicated_but \
whose_complexity_doesn't_involve_N_or_submacros
NFOR(1) NFOR(2) NFOR(3) NFOR(4) NFOR(5) NFOR(6)
NFOR(7) NFOR(8) NFOR(9) NFOR(10) NFOR(11) NFOR(12)

calls for the `cc -E | indent' tool strikes me as inexplicable.

James

Nov 14 '05 #32

P: n/a
"Old Wolf" <ol*****@inspire.net.nz> wrote in message
news:84**************************@posting.google.c om...
Chris Torek <no****@torek.net> wrote:
Old Wolf <ol*****@inspire.net.nz> writes:


Good point. However I have seen Dan Pop recommend this technique
and the OS should optimise sparse arrays by not reserving the space
until it is actually used. Speaking of Mr Pop, I haven't seen any
posts from him for a while.. what's up?


Indeed. I invoked His name in another thread (and was cautioned
appropriately) and received nary a word. I did get a slight anal
discomforture later in the week, tho.

--
Mabden
Nov 14 '05 #33

This discussion thread is closed

Replies have been disabled for this discussion.