while (1) vs. for ( ;; )

D

Default User

Charlie said:
What about my last proposition ?


It was pretty dumb too. If it's on the web, it's not there legally, and
me pointing it out would merely be assisting in several company
violations. I like my job. And its money.




Brian
 
T

Tim Rentsch

Richard Heathfield said:
Tim Rentsch said:


I'm saying that I wouldn't write such a loop. That isn't the same as
claiming that everybody must do likewise. :)

Oh. Well if that's all you're trying to say then there
might not be any lack of agreement after all. :)
 
C

Charlie Gordon

Default User said:
It was pretty dumb too. If it's on the web, it's not there legally, and
me pointing it out would merely be assisting in several company
violations. I like my job. And its money.

Well, this is a case of prejudice.
You should still do the test, even just to find out if any similar document lies
out there on the net.
You can then try and determine which of your company's and the other is the
original one...
If it appears Boeing's rights have been tampered with, you can report your find
to the company lawyer and may even get rewarded for it.
If it is the other way around, your opinion about the corporation might suffer,
but there would be no reason left to keep these effective coding standards from
comp.lang.c's avid readers.

As far as your job is concerned, this is a risk-free experience.

Chqrlie.
 
C

Christian Bau

"Charlie Gordon said:
As far as your job is concerned, this is a risk-free experience.

There are cases where just looking around on the web can be a problem.
 
B

Baxter

Keith Thompson said:
Because clear English is not necessarily clear C.

It's not your job to write to the machine or to the compiler. Your job is
to write to the next guy (probably yourself) who will be reading the code.
You've declared "done" and "mainloop" as variables, which means their
values could change.
Yep.

With "while (1)" (or "for (;;)") I can see at a
glance that the loop is an infinite one;

Infinity is a very long time. Your program will absolutely stop before
then.
with your suggestion, I can
never be sure unless I analyze the program and verify that "done" will
always be false (and then I'll wonder why the heck you used a
variable).

You could also use a #define -- while (PROGRAM_IS_RUNNING) {
The clear meaning of "while (!done)" is that the variable "done"
represents a condition that will become true when the loop is meant to
terminate.

That program WILL terminate sometime. If nothing else, when the power
switch is flipped.
I assume that anyone reading my code either is familiar with C, or
just won't be able to understand the code.
Not a good assumption. Even you can mis-read your own code on a bad day -
you'll wonder the next day how you could have written such code.
 
B

Baxter

Charlie Gordon said:
do not paraphrase code in comments.

I don't - I was illustrating how one would read this in English.
wrong assumption, but irrelevant.

Simple concepts are more effectively conveyed thru standard symbols*.
Fast english readers do not spell out words, or pronounce them in their heads.
Fast code readers do not like to have to read a lot of english, because in C
punctuation conveys more meaning than words.

"Fast readers" are going to miss something - especially if it is not in the
language they think in.
while (!done) looks a lot like while(done) or while (idone)

for (;;) is blatantly unambiguous.

And it has nothing to do with the action/job you're trying to describe.
Write your code so that it describes what the program does.
 
K

Keith Thompson

Baxter said:
It's not your job to write to the machine or to the compiler.

Of course it is.
Your job is to write to the next guy (probably yourself) who will be
reading the code.

That too.

If I write either "while (1)" or "for (;;)", the next guy will know
exactly what it means; if he doesn't, he's not going be able to
understand the rest of the program. Both are common C idioms.

If I write "while (mainloop)", the next guy won't know what it means
without tracking down what "mainloop" is. If he discovers that
"mainloop" is a variable (not a constant) of type bool, that happens
to be initiailized to true, and that is never changed, he's going to
do two things: change it to "while (1)" and track me down to ask what
I was thinking when I wrote the code.
 
W

websnarf

Tim said:
My experience is that there is less cognitive load if the
'while(1)' form is used. That is, when reading code, I can
read either form just fine, but something in my conscious
brain notices if the 'for(;;)' form is used, which slows
down my reading just a tiny bit. The 'while(1)' form gets
read and turned into "loop forever" without losing flow or
needing any conscious brain cycles. For these reasons --
that is, higher productivity -- I prefer the 'while(1)'
form.

I was surprised at how many people reported that a compiler
they use issues a warning for 'while(1)' and gave that as a
reason for giving preference to the 'for(;;)' form. It
seems like a choice should be made on the basis of what's a
better expression (lower defect rate, higher productivity,
better understood by the readers), not on the basis of some
errant warning message. Getting a warning on 'while(1)'
(assuming it can't be separately disabled) is a sign that
the person who wrote the warning code didn't think through
what he was doing, not that the construct is suspect. Style
choices should determine what kinds of warning messages come
out of the compiler, not the other way around.

These "defective warnings" come from *MANY* compilers and PC-LINT. I
agree with you that while(1) takes less default brainpower, but in the
end for(;;) has no more characters, so your brain will easily learn to
recognize that in its place. Like you I wish, the compiler warnings
and LINT programs went the other way, but they didn't. I don't know
why. But to really put some effort and making a fuss about this, I
need something else.

To me being able to say my code compiles "warning free" and 100% LINT
clean is extremely valuable. (It means that if anyone wants to
check/debug their modifications afterwards, they know that every
compiler/LINT warning will point to a modification they made that is
likely to be the place to look first.) This often forces me to write
my code slightly different from my default (like casting 'X' characters
to (char), since compilers will often make them ints by default.) But
its worth it. Because "automated checkers" are the cheapest set of
eyes looking over my shoulder to make sure my code is ok.

This heuristic has served me very well, regardless of what pain it
causes me. To give that up, just because while(1) is slightly better
intuitively, is just not a good trade off. Compiler warnings are
valuable to me -- my intuition being a replacement for accurate reading
of source code is not as valuable.
I myself would have no problem with people writing

FOREVER {
}

assuming a suitable '#define FOREVER <...>', _provided_ the
definition had made its way into a project-level include
file and was used and recognized by the team as a whole and
not just by some individuals. Doing that might be a way of
getting team consensus and simultaneously avoiding the whole
while/for discussion altogether.

Sure, but its a little nonstandard. The effort you put into propgating
and getting used to this, it seems to me, is not seriously different
from just standardizing on for(;;).
 
W

websnarf

Tim said:
One technique I was thinking of is, eg,

#define while(e) while( LOOPTRACK() && (e) )

which is a technique I've found useful in the past in some
situations. You can do something similar with 'for()', but
it doesn't work quite as well because of the syntax of the
'for' control expressions; in particular, it's hard to put
the call to 'LOOPTRACK()' before the first iteration. This
technique can be especially important for loops of the "near
infinite" variety.

How about:

#define for(x) for(LOOPTRACK(),x,LOOPTRACK())

?
 
W

websnarf

Keith said:
Of course, I meant "if (0 == a)", not "if (0 = a)".

Gloating over the irony of that typo is left as an exercise for the
reader.

You know how on the Daily Show with Jon Stewart, he'll occasionally
show a clip of some government official that's just so funny or
outrageous in of itself that he doesn't even say anything when the
camera comes back to him? He just makes some subtle facial gestures
and the audience is doubling over in laughter? You know what I'm
talking about?

That's what this reminded me of.
 
W

Wolfgang Riedel

grep -n 'while[ ]*([ ]*l[ ]*)'

to find them. (Add tabs next to the spaces inside brackets
<>snip

you didn't try said grep on any OS known to mankind, I guess.

On the other hand, this one will just do, what _I_ want:

grep -n ';;' *.c

Wolfgang
 
C

Charlie Gordon

How about:

#define for(x) for(LOOPTRACK(),x,LOOPTRACK())

Yeh, that's an idea! let's get the worst of both worlds :

// To settle the while(1) / for(;;) debate, here is a compromise :

for (; 1 ;) { ... }

Chqrlie.
 
T

Tim Rentsch

Wolfgang Riedel said:
grep -n 'while[ ]*([ ]*l[ ]*)'

to find them. (Add tabs next to the spaces inside brackets
<>snip

you didn't try said grep on any OS known to mankind, I guess.

In fact, I did. The command in the posting was copied
directly out of the shell script file that had the command
in it.

If you read the earlier posting again, you should see that
the point of the grep is to find while's that look like
'while(1)' but actually have a lowercase L, rather than 1,
as the control expression. The grep command above will do
that.
 
T

Tim Rentsch

How about:

#define for(x) for(LOOPTRACK(),x,LOOPTRACK())

?

A couple of problems:

1. Doing 'for(;;)' would then be a syntax error.

2. Usage like 'for( p=d, q=s; *q; p++, q++ )' would need to
be written with extra sets of parentheses for the first and
third expressions -- 'for( (p=d, q=s); *q; (p++, q++) )' --
so as to satisfy the preprocessor.

A similar requirement holds for while control expressions
that use the comma operator, but such cases are relatively
rare. It's fairly common to use multiple initializations
or multiple "next iteration actions" in for loops.
 
D

Default User

Charlie said:
Well, this is a case of prejudice.
Boggle.

You should still do the test, even just to find out if any similar
document lies out there on the net.

I "should" do what I feel comfortable with, not what usenet people want
me to do.



Brian
 
T

Tim Rentsch

These "defective warnings" come from *MANY* compilers and PC-LINT. I
agree with you that while(1) takes less default brainpower, but in the
end for(;;) has no more characters, so your brain will easily learn to
recognize that in its place. Like you I wish, the compiler warnings
and LINT programs went the other way, but they didn't. I don't know
why. But to really put some effort and making a fuss about this, I
need something else.

To me being able to say my code compiles "warning free" and 100% LINT
clean is extremely valuable. (It means that if anyone wants to
check/debug their modifications afterwards, they know that every
compiler/LINT warning will point to a modification they made that is
likely to be the place to look first.) This often forces me to write
my code slightly different from my default (like casting 'X' characters
to (char), since compilers will often make them ints by default.) But
its worth it. Because "automated checkers" are the cheapest set of
eyes looking over my shoulder to make sure my code is ok.

This heuristic has served me very well, regardless of what pain it
causes me. To give that up, just because while(1) is slightly better
intuitively, is just not a good trade off. Compiler warnings are
valuable to me -- my intuition being a replacement for accurate reading
of source code is not as valuable.

If you think using 'for(;;)' is a better match for you, given
the factors in your environment, by all means please use it.

On the other hand, don't assume that the factors and experience
of your environment must also apply to other people. My
experience using lint and other similar tools is different from
yours. Some warning messages seem cost-effective to enable;
others do not. The set of messages that seem cost-effective in
your environment doesn't necessarily match the sets in other
environments.

Incidentally, I didn't say "defective warnings", I said "errant
warning message". Please try to quote correctly, even in small
things.

Sure, but its a little nonstandard. The effort you put into propgating
and getting used to this, it seems to me, is not seriously different
from just standardizing on for(;;).

I take it you haven't measured (even informally) the cost
of either one? And you're now asserting that the costs
are the same?

Even if the costs are the same, the benefits of using
the 'FOREVER { ... }' form may be higher. In choosing
between alternatives, it's important to look at both
costs and benefits.
 
T

Tim Rentsch

Charlie Gordon said:
Tim Rentsch said:
Charlie Gordon said:
Assume the programmer always uses while(1) { ... }
for his endless loops. You quickly get used to interpreting
these automatically as you read them, without paying much
attention. What if there are some while(l) { ... } loops
as well. Will you always keep a sharp enough eye to catch
these correctly ?

This question has to deserve some kind of award for being a
strawman argument. If you need to find 'while(l)', it takes
only a few seconds to write a command:

grep -n 'while[ ]*([ ]*l[ ]*)'

to find them. (Add tabs next to the spaces inside brackets
if developers are prone to use tabs in the middle of lines.)

My intent was not to find such things, just to point out that there is a
possibility for misreading code and for miswriting it as well. That stupid
programmer might have meant while(l) and typed while(1) and then cannot tell the
difference because of a stupid Courier font. How will he/she find this bug ?

Oh. You know about a class of problems, but you don't want
to use the best tools to try to avoid them?

Pick a side. Either the problem is one that's important to
address, or it isn't. You can't have it both ways. If it's
important that the problem be addressed, I would expect any
competent software developer to try to find the most
cost-effective means of solving or avoiding it.

To go after poorly named variables, I would want to catch and flag all use of
variables named 'l' this way :
grep -nw l **/*.[hc]

To bad grep doesn't know how to ignore C comments and literals.

If grep doesn't solve this problem for you, it's really not
that difficult to write a specialized program that does
token search rather than string search. Assuming of course
that there isn't one already written that could be found
with a short web search.

Fixing them might take as long as two or three minutes; so
to save you the trouble, here's a command for that:

sed 's:\(while[ ]*(\)[ ]*l[ ]*):\1 l /*** L, NOT 1! ***/ ):'

Please feel free to use either or both of these aids
to help identify or correct such egregious code.

Thank you professor, you are so grand!
You will note that this sed script will break code where the while(l) appears in
/* comments */
or change code behaviour if it appears in C strings.

Yes, that's a shortcoming. Do you expect such things to
actually occur, or is this just a silly objection for the
purpose of scoring debate points?

In either case, both conditions are easily addressed.

1. In cases where 'while(l)' appears inside comments, the
new code will get an error message out of the compiler.
Use an editor and fix the problem. (Does anyone still
use comments rather than '#if 0' to comment out sections
of code?)

2. In cases where 'while(l)' appears inside strings (or
character literals), these can be found easily using
diff and grep. Use an editor and fix them.


When I wrote my earlier response, I assumed that there some
level of legitimate concern for an actual potential problem.
Now it appears that you are objecting solely for the purpose
of raising objections, and not because you have any interest
in solving a problem. If so, please do everyone a favor and
just go away.
 
A

Alan Balmer

It's not your job to write to the machine or to the compiler. Your job is
to write to the next guy (probably yourself) who will be reading the code.
Do you know any C programmer who would have difficulty reading this
code? Would you?
Infinity is a very long time. Your program will absolutely stop before
then.

You are unfamiliar with the term "infinite loop"?
You could also use a #define -- while (PROGRAM_IS_RUNNING) {
Why? Since we are indeed writing a computer program, not a novel, I
still have to go find the definition of PROGRAM_IS_RUNNING.
That program WILL terminate sometime. If nothing else, when the power
switch is flipped.

Are you saying that the power switch will change the value of "done"?
I suspect that's implementation-dependent.
Not a good assumption. Even you can mis-read your own code on a bad day -
you'll wonder the next day how you could have written such code.

Much more likely to happen if you obfuscate the code in the ways
you're suggesting.
 
F

Flash Gordon

These "defective warnings" come from *MANY* compilers and PC-LINT.

I don't consider the warning to be defective. You can have conditions
which always evaluate to true or false for a number of reasons:

1) It will evaluate to a different value on some other implementation
leading to different behaviour and this is correct.
Why not use #if to select the appropriate behaviour so that it is
obvious that it never changes for a given build?

2) You are doing an "infinite" loop (it might break out from the middle)
and the for (;;) idiom can be used in this instance.

3) You've made an error (maybe due to mixing signed and unsigned or
something) and the condition should *not* always evaluate to the same
value.

How many instances are there where you need a conditional with a
constant expression that can't be easily implemented using #if or for
(;;) or similar? If you can't find any, then by not having the warning
you would be throwing away the chance for the tools to inform you of
real errors.
> I
agree with you that while(1) takes less default brainpower, but in the
end for(;;) has no more characters, so your brain will easily learn to
recognize that in its place.

for (;;) does not (and never has) taken *me* any more brain power, since
I see immediately that there is no termination condition so the loop is
never terminated from there. Of course, other people might find it takes
more work to read.
> Like you I wish, the compiler warnings
and LINT programs went the other way, but they didn't. I don't know
why. But to really put some effort and making a fuss about this, I
need something else.

I prefer to have compilers warn about conditionals that always evaluate
to the same value.
To me being able to say my code compiles "warning free" and 100% LINT
clean is extremely valuable. (It means that if anyone wants to
check/debug their modifications afterwards, they know that every
compiler/LINT warning will point to a modification they made that is
likely to be the place to look first.) This often forces me to write
my code slightly different from my default (like casting 'X' characters
to (char), since compilers will often make them ints by default.) But
its worth it. Because "automated checkers" are the cheapest set of
eyes looking over my shoulder to make sure my code is ok.
Agreed.

This heuristic has served me very well, regardless of what pain it
causes me. To give that up, just because while(1) is slightly better
intuitively, is just not a good trade off. Compiler warnings are
valuable to me -- my intuition being a replacement for accurate reading
of source code is not as valuable.

For me while(1) is not more intuitive than for (;;). I'm not disputing
it is for you, just pointing out that for some of us there is not the
down side you have.
Sure, but its a little nonstandard. The effort you put into propgating
and getting used to this, it seems to me, is not seriously different
from just standardizing on for(;;).

I definitely agree here. Both while(1) and for(;;) are perfectly clear
if you no C, and I can see no instance where you would want to change
all instances of FOREVER to something other than an infinite loop, so it
adds something non-standard to be learned (you have to learn to always
use it) with no significant benefit that I can see.
 
K

Keith Thompson

Flash Gordon said:
Tim Rentsch wrote: [...]
I was surprised at how many people reported that a compiler
they use issues a warning for 'while(1)' and gave that as a
reason for giving preference to the 'for(;;)' form. It
seems like a choice should be made on the basis of what's a
better expression (lower defect rate, higher productivity,
better understood by the readers), not on the basis of some
errant warning message. Getting a warning on 'while(1)'
(assuming it can't be separately disabled) is a sign that
the person who wrote the warning code didn't think through
what he was doing, not that the construct is suspect. Style
choices should determine what kinds of warning messages come
out of the compiler, not the other way around.
These "defective warnings" come from *MANY* compilers and PC-LINT.

I don't consider the warning to be defective. You can have conditions
which always evaluate to true or false for a number of reasons:

1) It will evaluate to a different value on some other implementation
leading to different behaviour and this is correct.
Why not use #if to select the appropriate behaviour so that it is
obvious that it never changes for a given build?

2) You are doing an "infinite" loop (it might break out from the middle)
and the for (;;) idiom can be used in this instance.

3) You've made an error (maybe due to mixing signed and unsigned or
something) and the condition should *not* always evaluate to the same
value.

Yes, a lint-like tool or a smart compiler should be able to warn about
conditions that always evaluate to true or false. But anything clever
enough to warn about constant conditions should be clever enough to
recognize the common "while (1)" idiom and shut up about it.

That doesn't, of course, mean that all such tools actually do make
this distinction, and we still have to deal with the ones that don't.
But if you're using something that warns about "while (1)" but not
about the equivalent "for (;;)", you might consider submitting a bug
report.
 

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

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top