while (1) vs. for ( ;; )

C

Christian Bau

Christopher Benson-Manica said:
Would you suppose that such a view is common in the world of
professional programming? My work experience is still quite limited,
and it's hard to tell ubiquitous programming conventions from
idiosyncratic oddities...

There are different styles. A relatively common one goes like this: At
the start of a function, lots of quick checks for error conditions,
trivial calls, etc. with quick returns. Then the actual work is done,
and there is one single return at the end of the function. Sometimes the
return statement has a label with goto statements going to that label,
sometimes nested if's or multiple if's are used.

Multiple returns within the function body (after the initial quick
checks) can be a huge maintenance problem, if you find out you have to
add some code that needs executing before returning from the function.

People have different styles, and if people tell you "always do X" then
often X is correct 99% of the time, and with some experience you will
know when you run into the 1% when "always do X" is wrong.
 
D

Default User

Charlie said:
Would you mind posting these ?
Coding Standards so effective would be very helpful around here.


1. They are fairly long.

2. They are not text files.

3. They are most assuredly copyrighted by the company.

4. They are most assuredly considered sensitive information by the
company.


The first two would preclude posting to this newsgroup (besides
possibly being off-topic). The second two would preclude posting them
anywhere.



Brian
 
A

akarl

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.

That's OK (unless you have argued in favor of the design choice of using
`=' for assignment in C ;-)

August
 
C

Christian Bau

Tim Rentsch said:
However, I don't believe that all "infinite-but-not-really"
loops benefit from this kind of rewriting. Even for loops
with only one exit condition, sometimes having the only loop
exit be a break (or return) in the middle of the loop body
is the clearest expression of what the loop is supposed to
do. At least, that has been my experience.

Example:

for (;;) {

/* Quite a bit of code to find the next candidate */
if (no more candidates) break;

/* Check if this candidate can be ignored */
if (candidate can be ignored) continue;

/* Do the real work */
do_some_work ();
}

You can easily change this into "structured" code, but it doesn't
improve it.
 
C

Charlie Gordon

akarl said:
You don't see the point. The `bool' type in stdbool.h is primarily for
(self) documentation purposes. That a lint tool such as Splint can
detect incorrect usage is an extra bonus.

Actually, I have been using an equivalent user type for years, like most
programmers I know.
It was not really a type, just a typedef and a pair of #define for TRUE and
FALSE
stdbool goes a little bit beyond that, but cannot fix the lack of a true boolean
paradigm in C, and lowercase true and false make me think too much of java...

So I agree with your point, but still prefer for(;;)

Chqrlie.
 
C

Charlie Gordon

Default User said:
Charlie Gordon wrote:


1. They are fairly long.

2. They are not text files.

Just post a link.
3. They are most assuredly copyrighted by the company.

Which company is that ?
4. They are most assuredly considered sensitive information by the
company.

I won't tell ;-)
The first two would preclude posting to this newsgroup (besides
possibly being off-topic). The second two would preclude posting them
anywhere.

OK, too bad, but do this simple test :
Select a dinstinctive phrase from this document, and submit it to google.
would you mind then telling us the phrase or location of whatever copies happen
to already sit on the web ?

Just curious.

Chqrlie.
 
C

Charlie Gordon

Keith Thompson said:
I won't try to speak for pete, but since "while (1)" and "for (;;)"
are semantically identical, I'd be very surprised if there were any
difference in defect rate. It's something that seems so obvious to me
that I wouldn't bother trying to measure it without a very good
reason. If there were a difference, I'd tend to assume that it's a
difference in training (perhaps the books or classes that use one form
happen, by coincidence to be better than the ones that use the other
form). Do you have some reason to think there's a significant
difference?

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 ?

I prefer for(;;). That way anything that looks like while(l) will catch my eye,
and I will no doubt complain about such a poor choice for a variable name.

Therefore, I agree while(1) is more prone to indirectly causing defect than
for(;;).

Chqrlie.
 
B

Baxter

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 ?

I prefer for(;;). That way anything that looks like while(l) will catch my eye,
and I will no doubt complain about such a poor choice for a variable name.

Therefore, I agree while(1) is more prone to indirectly causing defect than
for(;;).

Why not code it like you would read it in English:

bool done = false;
while (!done) { // while not done do
...

bool mainloop = true;
while (mainloop) { // while mainloop do
...


You can further document it like this:
while (!done) { // will never be done while computer is running
...

There's many variations on this:

#define NOTDONE 1
...
while (NOTDONE) {
...

Convey your intent in English (assuming English is your first language)
 
C

Chris McDonald

Baxter said:
You can further document it like this:
while (!done) { // will never be done while computer is running
...

Convey your intent in English (assuming English is your first language)


Or, in better English:

while (!done) { // will never terminate while computer is running

as it will be *done*, just not *finished*.
 
K

Keith Thompson

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 ?

Any code that declares a variable called "l" has worse problems than
while() vs. for().

In well-written code, something that looks like "while (1)" *is*
"while (1)"; I don't have to waste my time distinguishing between '1'
and 'l'.
 
K

Keith Thompson

Baxter said:
Why not code it like you would read it in English:

bool done = false;
while (!done) { // while not done do
...

bool mainloop = true;
while (mainloop) { // while mainloop do
...

Because clear English is not necessarily clear C.

You've declared "done" and "mainloop" as variables, which means their
values could change. With "while (1)" (or "for (;;)") I can see at a
glance that the loop is an infinite one; 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).

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.

I assume that anyone reading my code either is familiar with C, or
just won't be able to understand the code.
 
C

Charlie Gordon

Keith Thompson said:
Any code that declares a variable called "l" has worse problems than
while() vs. for().

I agree completely, as I explain it in the very same post.
In well-written code, something that looks like "while (1)" *is*
"while (1)"; I don't have to waste my time distinguishing between '1'
and 'l'.

There isn't so much "well-written" code out there ;-)
Well-written code definitely has to adhere to strict Coding Rules.
Among these is a golden one: consistency. This means in particular that simple
constructs should be implemented the same way everywhere. Coding Rules should
define the "standard" way to implement indefinite loops, be it for(;;),
while(1), while(true) FOREVER... and the programmer is required to use whatever
was decided.

I personnally read a lot of code, well-written and not: in my experience,
something that looks like a while (1) can sometimes be a while (l), so I am
extra careful with these, while (1) makes me suspicious. It is a matter of
style, but also of maturity: I have oserved that skilled experienced programmers
tend to use for (;;) more than while (1), whereas beginners will think of
while(! done) and java natives will prefer while (true). while (1) comes a
distant second in this list. This is a statistical approach, one of many that
help figuring the skill level of the programmer when code proofing: I don't look
for the same kind of bugs in beginner's code and in expert's code. And there
will be bugs: C has pitfalls for all levels.

Chqrlie.
 
C

Charlie Gordon

Baxter said:
Why not code it like you would read it in English:

bool done = false;
while (!done) { // while not done do

do not paraphrase code in comments.
bool mainloop = true;

you probably want to make this a const
while (mainloop) { // while mainloop do

useless comments are a pain.
...


You can further document it like this:
while (!done) { // will never be done while computer is running

why require so many words for something so simple?

How much commenting will you resort to the really complicated stuff?
...

There's many variations on this:

#define NOTDONE 1
...
while (NOTDONE) {
...

Convey your intent in English (assuming English is your first language)

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.

while (!done) looks a lot like while(done) or while (idone)

for (;;) is blatantly unambiguous.

Chqrlie.

*: this is a requirement in multicultural areas, road signs are a good example:
they are not used so much in the US, where everything is written, sometimes even
abbreviated beyond repair (what is a PED XING? where is B'WY/NY?)
 
T

Tim Rentsch

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.)

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.


I prefer for(;;). That way anything that looks like
while(l) will catch my eye, and I will no doubt complain
about such a poor choice for a variable name.

Therefore, I agree while(1) is more prone to indirectly
causing defect than for(;;).

It seems highly unlikely that any increase in defect rate
could measured out of the noise of defects in code produced
by people who would use the letter 'l' as a variable name
(especially in the context of a 'while' expression!) in the
first place. However, you're welcome to try to measure it.
 
A

Alan Balmer

Example:

for (;;) {

/* Quite a bit of code to find the next candidate */
if (no more candidates) break;

/* Check if this candidate can be ignored */
if (candidate can be ignored) continue;

/* Do the real work */
do_some_work ();
}

You can easily change this into "structured" code, but it doesn't
improve it.

A good example. I see this pattern a lot.
 
A

Alan Balmer

Why not code it like you would read it in English:
Because it's not English, it's C. Doing this makes the C code less
clear, since you have to verify what "done" and "mainloop" are, and
also verify that they are not changed anywhere. Both "while (1)" and
"for (;;)" are self-documenting. It's absolutely certain what they do,
and no comments are needed.
 
R

Richard Heathfield

Tim Rentsch said:
Do you really mean to say that _no_ loop, at any
time under any conditions, should be written with a constant
control expression? Not counting of course examples like
the microwave oven driver loop, which you explained already.

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

Charlie Gordon

Default User said:
I have 24+ years in and would feel pretty damn stupid getting fired
over something like that.

What about my last proposition ?

Chqrlie.
 
C

Charlie Gordon

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 ?

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.
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.

Chqrlie.
 

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

Forum statistics

Threads
473,777
Messages
2,569,604
Members
45,218
Latest member
JolieDenha

Latest Threads

Top