# Programmers: please learn when to not use while loops

**URL:** <https://boards.straightdope.com/t/programmers-please-learn-when-to-not-use-while-loops/244841>\
**Category:** The BBQ Pit\
**Created:** [May 12, 2004, 7:54pm UTC](https://boards.straightdope.com/t/programmers-please-learn-when-to-not-use-while-loops/244841 "2004-05-12T19:54:27Z")\
**Posts on this page:** 20\
**Page:** 4

<div class="post-metadata">

**Author:** ![c\_goat](https://avatars.discourse-cdn.com/v4/letter/c/f4b2a3/32.png) [@c\_goat](https://boards.straightdope.com/u/c_goat)\
**Post date:** [May 13, 2004, 8:29pm UTC](https://boards.straightdope.com/t/programmers-please-learn-when-to-not-use-while-loops/244841/61 "2004-05-13T20:29:11Z")

</div>

Dammit, why didn’t I notice there was a second page that already covered that!? :smack:

---

<div class="post-metadata">

**Author:** ![Bytegeist](https://avatars.discourse-cdn.com/v4/letter/b/9dc877/32.png) [@Bytegeist](https://boards.straightdope.com/u/Bytegeist)\
**Post date:** [May 13, 2004, 10:51pm UTC](https://boards.straightdope.com/t/programmers-please-learn-when-to-not-use-while-loops/244841/62 "2004-05-13T22:51:45Z")

</div>

Sorry if this is not quite on-topic.

Many years ago I was enrolled in an undergraduate Operating Systems course for which we had to learn i386 assembly language. By this time I already had a lot of experience programming the 6502, the 6809, the Z80, and the M68000, so learning the i386 was straightforward. For other students in the class though, it was clearly a challenge.

For one particular assignment, we had to solve some problem (I forget what) in i386 assembly code. On the day we turned in our program listings the professor _re-distributed_ our submissions randomly among the class, so that we could go through a kind of peer review process. I’m not sure why he did this, and curiously he never did it a second time — but anyway the task was to “grade” your classmate’s work, writing your own comments and suggestions on it in red ink, and then hand this back in for the next class. Fortunately for me, as you’re about to see, the student grading was non-binding.

On the next class we handed in our graded versions of each other’s work. I don’t remember anything about the program I reviewed. It must have been decent enough. Then finally on the next class after that, we received our own work back, now marked with both the professor’s commentary as well as commentary from one of our anonymous peers.

The professor gave me a near perfect score, but the student dinged me for writing inefficient code. What was my “error”?

At the time, I was fond of writing my assembly language subroutines like this:

```auto

SOME_ROUTINE:
; [Block-comment documentation of the routine goes here.]

  [Routine body goes here, end-of-line comments as needed.]
  RET

```

You can see the flaw now I’m sure. The guy dinged me of course because I put a big comment _after_ the routine’s opening label. His remark was that at runtime, whenever my routine was called, the computer would be wasting time _processing the comment_.

Ig… oooog… grrrr… mmmmmph… RARRRRH!

---

<div class="post-metadata">

**Author:** ![EllisDee](https://sea3.discourse-cdn.com/straightdope/user_avatar/boards.straightdope.com/ellisdee/32/4531_2.png) [@EllisDee](https://boards.straightdope.com/u/EllisDee)\
**Post date:** [May 14, 2004, 12:12am UTC](https://boards.straightdope.com/t/programmers-please-learn-when-to-not-use-while-loops/244841/63 "2004-05-14T00:12:02Z")

</div>

> [@LordVor](#):
>
> As for gotos, here’s another case where I’ve blanked on a better way of doing it:
> 
> ```auto
> 
> switch (x) {
> case 0:
> //do some stuff
> goto otherstuff;
> case 1:
> // do some stuff that's different than case 0
> otherstuff:
> //do otherstuff;
> break;
> //5 other cases here
> }
> 
> ```
> 
> Sure, I can make an “otherstuff” funciton and call it in both cases, but sometimes you can’t take the overhead of another function call…
> 
> -lv

First off, if efficiency is an issue, I’d be careful with the switches.

Regarding your goto quandries, the first example was answered the same way I would have, using returns. This one I’d handle with a variable:

```auto

otherstuff = 0;
switch (x)
{
  case 0:
    //do some stuff
    otherstuff = 1;
    break;
  case 1:
    // do some stuff that's different than case 0
    otherstuff = 1;
    break;
  //5 other cases here
}
if (otherstuff==1)
{
  //do otherstuff;
}

```

Forgive any syntax errors; I haven’t written in C in forever.

---

<div class="post-metadata">

**Author:** ![MilTan](https://avatars.discourse-cdn.com/v4/letter/m/71e660/32.png) [@MilTan](https://boards.straightdope.com/u/MilTan)\
**Post date:** [May 14, 2004, 3:25am UTC](https://boards.straightdope.com/t/programmers-please-learn-when-to-not-use-while-loops/244841/64 "2004-05-14T03:25:41Z")

</div>

> [@Monstre](#):
>
> In C/C++, you can state even more broadly – all loops can be re-written as any of the other loops - pick your favorite… (except for the effect of declaring a loop counter in the for-header, which has scope for all runs of the loop, but not outside… with while loops, gotta do it before the loop begins)
> 
> But I still encourage my students to use good practices and use for-loops for counting situations and while or do/while for logical exit situations. I don’t expect them all to program as efficiently as possible yet – they’re learning. But have to try to discourage bad habits and encourage good ones.

Hmm… don’t you also run into trouble with the effect of **break** and **continue** statements? You could still easily simulate a **while** loop with a **for** loop, but to do the opposite would require a **goto**.

As to your second point, I agree with you. But the OP actually suggests using a **for** loop to do linked list traversal, as well, which I don’t think counts as a “counting situation.”

I guess it’s a matter of programming practice, but my own style generally dictates that dynamic data structures get traversed with **while** loops, while arrays and the like (as well as standard counting loops) get traversed with a **for**. In general, when the increment statement (not the loop test) of the loop is complex (read: more than i++ or i += 3), I prefer a **while** loop.

---

<div class="post-metadata">

**Author:** ![pervert](https://avatars.discourse-cdn.com/v4/letter/p/bbe5ce/32.png) [@pervert](https://boards.straightdope.com/u/pervert)\
**Post date:** [May 14, 2004, 4:46am UTC](https://boards.straightdope.com/t/programmers-please-learn-when-to-not-use-while-loops/244841/65 "2004-05-14T04:46:37Z")

</div>

> [@catsix](#):
>
> I weep.

I once knew a programmer who put halts after evey one of his jumps (assembly code don’t you know) “just in case”.

Of course, this was when microprocessors were new enough that a little skepticism was in order. Still, you have to make _a few_ assumptions.

I agree with you. There are instances where surperflous code is just that.

---

<div class="post-metadata">

**Author:** ![LordVor](https://avatars.discourse-cdn.com/v4/letter/l/90ced4/32.png) [@LordVor](https://boards.straightdope.com/u/LordVor)\
**Post date:** [May 14, 2004, 5:00am UTC](https://boards.straightdope.com/t/programmers-please-learn-when-to-not-use-while-loops/244841/66 "2004-05-14T05:00:14Z")

</div>

> [@Ellis Dee](#):
>
> First off, if efficiency is an issue, I’d be careful with the switches.

Well, yeah, especially on a processor with a deep pipeline. But I can only rewrite so much code to be more efficient. Believe me, I’m trying to get rid of the switches. Your way makes sense, although it does add another conditional branch (but again, I can’t complain about that much, since there’s already a big-asses switch statement in the routine).

**Miltan** , personally, I don’t care how complex the incrementor or the test is. If you have an initializer, an incrementor, and a test, then you should be using the looping statement that’s designed to deal with an initializer, and incrementor, and a test, and not the looping statement that just tests.

---

<div class="post-metadata">

**Author:** ![MilTan](https://avatars.discourse-cdn.com/v4/letter/m/71e660/32.png) [@MilTan](https://boards.straightdope.com/u/MilTan)\
**Post date:** [May 14, 2004, 5:20am UTC](https://boards.straightdope.com/t/programmers-please-learn-when-to-not-use-while-loops/244841/67 "2004-05-14T05:20:57Z")

</div>

> [@LordVor](#):
>
> **Miltan** , personally, I don’t care how complex the incrementor or the test is. If you have an initializer, an incrementor, and a test, then you should be using the looping statement that’s designed to deal with an initializer, and incrementor, and a test, and not the looping statement that just tests.

Now hang on a second. What’s to determine if the code I have in a loop is an “incrementor”? What about searching a binary tree? It’s not amazingly different from traversing a linked list. I could certainly write it as a nice compact for loop:

```auto

for (TreePtr *p = root; (p != NULL) && (p->d != value); 
       p = (p->d < value)?p->left:p->right);

```

But I find that it makes more sense as a while loop:

```auto

TreePtr *p = root;
while ((p != NULL) && (p->d != value)) {
   if (p->d < value) {
      p = p->left;
   } else {
      p = p->right;
   }
}

```

Now, obviously this is a slightly contrived example, but my general point is that one person’s “incrementor” is another person’s “too complex to put into a for-loop.” And a lot of times, a “proper” use of a while loop just hides the incrementor anyway, such as your queue.get() example. I’m not trying to start a holy war, or anything, just trying to argue that different coding styles call for different loop constructs.

---

<div class="post-metadata">

**Author:** ![Monstre](https://avatars.discourse-cdn.com/v4/letter/m/e274bd/32.png) [@Monstre](https://boards.straightdope.com/u/Monstre)\
**Post date:** [May 14, 2004, 6:08am UTC](https://boards.straightdope.com/t/programmers-please-learn-when-to-not-use-while-loops/244841/68 "2004-05-14T06:08:32Z")

</div>

> [@Shade](#):
>
> My advice: make it explicit (if you don’t already). Say “It should reverse the order of the digits of any positive integer. Here is an example, but it has to work in other places as well. If it ends with a zero, it’s ok for this to be dropped when it becomes leading.”

That’s the sad part. I **do** make the specification explicit. I’m always careful to specify exactly what a function should do. Then I try to provide an example or two to help illustrate the usage. Same applies for assignments I give – my specs are always as precise and complete as possible.

---

<div class="post-metadata">

**Author:** ![John\_Kentzel-Griffin](https://avatars.discourse-cdn.com/v4/letter/j/ccd318/32.png) [@John\_Kentzel-Griffin](https://boards.straightdope.com/u/John_Kentzel-Griffin)\
**Post date:** [May 14, 2004, 6:15am UTC](https://boards.straightdope.com/t/programmers-please-learn-when-to-not-use-while-loops/244841/69 "2004-05-14T06:15:45Z")

</div>

> [@catsix](#):
>
> I’m a she, but yes, that’s what I was talking about. For example, I had a student who would do things like initialize a counter variable at the beginning of a program, then initialize it again directly before the for(i = 0; i \< 20; i++) line. When I asked that student why they had initialized ‘i’ three times, especially as it was used nowhere else in 60odd lines of code, he replied ‘In case the computer didn’t understand it the first time.’
> 
> So yes, I want them to be safe, just not tinfoil helmet safe.

At one of the places I worked, there was a consultant who would alway move spaces to a character field immediately before moving in the desired string. When I tried to tell her this was unnecessary, she said she just wanted to be _sure_ the variable was cleared. :rolleyes: She was the one who gave me the technical interview for the position.

---

<div class="post-metadata">

**Author:** ![Monstre](https://avatars.discourse-cdn.com/v4/letter/m/e274bd/32.png) [@Monstre](https://boards.straightdope.com/u/Monstre)\
**Post date:** [May 14, 2004, 6:23am UTC](https://boards.straightdope.com/t/programmers-please-learn-when-to-not-use-while-loops/244841/70 "2004-05-14T06:23:41Z")

</div>

> [@](#):
>
> from _MilTan_  
> Hmm… don’t you also run into trouble with the effect of break and continue statements? You could still easily simulate a while loop with a for loop, but to do the opposite would require a goto.

Just curious – what’s the scenario you are envisioning here? Do you mean converting a for-loop that uses a continue into a while-loop with the same functionality would need a goto? Or was it something else you were envisioning? Example?

If the former:

```auto

for (initial condition; test-condition; iterator-statement)
{
    // some stuff
    if (some-condition)
         continue;

    // possibly some other stuff

}

```

just becomes:

```auto

initial condition
while (test-condition)
{
    // some stuff
    if (some-condition)
    {
          iterator-statment // (since would occur after 'continue' in for-loop above)
          continue;
    }
    // possibly some other stuff
    iterator-statement
}

```

Don’t see a need for “goto” here. Or perhaps you were thinking of something else? If so, could you give an example?

Not that I would do it with a while, instead – just saying that C/C++ loops are just basic flowcharts and not implemented with rigid rules on when you have to use a specific type. Even though there are **conventions** on which ones are best to use when. For me, I’ll pick a for-loop for situations when the for-header best encapsulates the exact information about the control of the loop. But it doesn’t preclude the possibility of writing an equivalent loop as a while or a do-while. (again, except for the scope issue of a variable like “count” declared in a for-header, like this):

```auto

for (int count = 0; count < 10; count++)
{

}

```

---

<div class="post-metadata">

**Author:** ![MilTan](https://avatars.discourse-cdn.com/v4/letter/m/71e660/32.png) [@MilTan](https://boards.straightdope.com/u/MilTan)\
**Post date:** [May 14, 2004, 4:21pm UTC](https://boards.straightdope.com/t/programmers-please-learn-when-to-not-use-while-loops/244841/71 "2004-05-14T16:21:00Z")

</div>

**Monstre** :  
Ahh, I see. For some reason, I wasn’t thinking about it like that. I was thinking of keeping the iterator statement at the end, instead of putting it before all continues. This would then involve replacing any continue with a “goto iteratorstatement.” Your way definitely makes sense. Of course, in the end, using the goto statements would essentially mimic what the compiled assembly code would do, anyway (optimizations notwithstanding)

---

<div class="post-metadata">

**Author:** ![Bill\_H](https://avatars.discourse-cdn.com/v4/letter/b/a5b964/32.png) [@Bill\_H](https://boards.straightdope.com/u/Bill_H)\
**Post date:** [May 15, 2004, 6:46pm UTC](https://boards.straightdope.com/t/programmers-please-learn-when-to-not-use-while-loops/244841/72 "2004-05-15T18:46:42Z")

</div>

(only read the OP; I’m sure others have made this comment as well):

If you’ve achieved a position where you review the code of others, you really shouldn’t be worrying about this. Using while’s is a perfectly valid method. When the code hits the processor, it’s likely to be identical to a for. In some situations, reasonable people could find using a while more readable than a for, even if a for were possible. When you make this sort of comment as part of your review, you diminish the value of your review, and more importantly, you diminish your respect among your team.

Now, if you just say aloud every once in a while, “I sure prefer a nice **for** when a **for** is called for,” that’s a different beast. Everyone has their own pet-peeves; lord knows I have mine. But if you “correct” every while you see, you’re really doing yourself (and your team) a disservice, and in the long run, you’ll be taken less seriously than if you concentrate on real issues.

---

<div class="post-metadata">

**Author:** ![kushiel](https://avatars.discourse-cdn.com/v4/letter/k/bbce88/32.png) [@kushiel](https://boards.straightdope.com/u/kushiel)\
**Post date:** [May 16, 2004, 1:32am UTC](https://boards.straightdope.com/t/programmers-please-learn-when-to-not-use-while-loops/244841/73 "2004-05-16T01:32:55Z")

</div>

Only when printing out tables of data would our teacher encourage us to do:

```auto

for (i = 0; i < 10; i++) 
{ 
//do stuff 
}

```

Otherwise, it is:

```auto

i = 0;

for
{
i++;
//do stuff
}
while (i < 10);

```

Fun being a high school student.

---

<div class="post-metadata">

**Author:** ![kushiel](https://avatars.discourse-cdn.com/v4/letter/k/bbce88/32.png) [@kushiel](https://boards.straightdope.com/u/kushiel)\
**Post date:** [May 16, 2004, 1:35am UTC](https://boards.straightdope.com/t/programmers-please-learn-when-to-not-use-while-loops/244841/74 "2004-05-16T01:35:55Z")

</div>

Or a Do While loop. _kicks self_

Hey, it is a testament to my teacher, not me, okay? :smack:

---

<div class="post-metadata">

**Author:** ![Monstre](https://avatars.discourse-cdn.com/v4/letter/m/e274bd/32.png) [@Monstre](https://boards.straightdope.com/u/Monstre)\
**Post date:** [May 16, 2004, 10:28pm UTC](https://boards.straightdope.com/t/programmers-please-learn-when-to-not-use-while-loops/244841/75 "2004-05-16T22:28:26Z")

</div>

A for-while loop… heh. Better get yourself a new teacher, **kushiel**. 😉

---

<div class="post-metadata">

**Author:** ![LordVor](https://avatars.discourse-cdn.com/v4/letter/l/90ced4/32.png) [@LordVor](https://boards.straightdope.com/u/LordVor)\
**Post date:** [May 17, 2004, 4:17am UTC](https://boards.straightdope.com/t/programmers-please-learn-when-to-not-use-while-loops/244841/76 "2004-05-17T04:17:31Z")

</div>

> [@Bill H.](#):
>
> When you make this sort of comment as part of your review, you diminish the value of your review, and more importantly, you diminish your respect among your team.

Which is why I didn’t fucking say it in the review, I said it in this-here lame-assed pit thread. I will also say, however, there there are pretty damned few places where spending three lines of code to spell out the while loop is “easier to read” then one line of a for loop.

**MilTan** , point taken. The ? operator has got to be the least-intuitive operator used in a production OS, (I still, occasionally, have to look up which side of the : is “true”) and if you can’t do the incrementor without it, you should be in a while loop, for readability’s sake.

-lv

---

<div class="post-metadata">

**Author:** ![Shalmanese](https://avatars.discourse-cdn.com/v4/letter/s/45deac/32.png) [@Shalmanese](https://boards.straightdope.com/u/Shalmanese)\
**Post date:** [May 17, 2004, 5:03am UTC](https://boards.straightdope.com/t/programmers-please-learn-when-to-not-use-while-loops/244841/77 "2004-05-17T05:03:14Z")

</div>

**catsix** I think you picked just about the worst possible example to illustrate your case. NEVER assume a number will always be positive and NEVER assume that % 2 numbers will always return a 0 or a 1.

The really crappy thing about software is that one tiny change somewhere in your program will cause a different function 2000 lines away to unexpectedly break. What if you decided to run it in hex to save speed and changed the %2 to %16 and missed one condition? What if your directly pushing a return value through and forgot to check if it returns -1 for error? Program specs change, and 10 seconds writing “useless” guard conditions now can save many hours of heartache.

For example, if their code was:

```auto

char * message;
if (x == 0)
    message = "you typed 0
";
else if (x == 1)
    message = "you typed 1
";
return message;

```

if x is neither 1 or 0, your going to return a pointer to random garbage which might be chucked through other convoluted processes which completely obscure the original bug. It might eventually end up as something so completely unreleated like your mouse pointer becoming corrupted and you would have no idea why this had happened. Far better to be safe than sorry.

---

<div class="post-metadata">

**Author:** ![Spectre\_of\_Pithecanthropus](https://sea3.discourse-cdn.com/straightdope/user_avatar/boards.straightdope.com/spectre_of_pithecanthropus/32/12343_2.png) [@Spectre\_of\_Pithecanthropus](https://boards.straightdope.com/u/Spectre_of_Pithecanthropus)\
**Post date:** [May 17, 2004, 1:42pm UTC](https://boards.straightdope.com/t/programmers-please-learn-when-to-not-use-while-loops/244841/78 "2004-05-17T13:42:32Z")

</div>

I only wish I could have used loops in my last project. I had to write it in straight SQLPLUS, so I had to have three passes through the data in separate inline views, to gather subtotals at three levels. Because of the way the table relationships I couldn’t use the canned COMPUTE function.

---

<div class="post-metadata">

**Author:** ![catsix](https://avatars.discourse-cdn.com/v4/letter/c/e19b73/32.png) [@catsix](https://boards.straightdope.com/u/catsix)\
**Post date:** [May 17, 2004, 2:13pm UTC](https://boards.straightdope.com/t/programmers-please-learn-when-to-not-use-while-loops/244841/79 "2004-05-17T14:13:27Z")

</div>

> [@](#):
>
> **Shalmanes** said:  
> What if you decided to run it in hex to save speed and changed the %2 to %16 and missed one condition? What if your directly pushing a return value through and forgot to check if it returns -1 for error? Program specs change, and 10 seconds writing “useless” guard conditions now can save many hours of heartache.

You might want to go back through this thread and read the rest of my posts before you continue jumping in my shit for that. There are no 'what if’s to that **example** and there are no ‘program specs change’ to something that gets a thirty second mention in a two hour lecture.

I guess you also missed it when I said that they’re not wasting ten seconds, they’re wasting **hours** doing useless shit in their programs. Instead of writing

if(i \>= 5)  
{  
//do stuff  
}

they write

switch(i)  
case 5:  
case 6:  
case 7:  
…  
case 99:  
case 100: //do something

Then they’re asking me for extensions because they spent two weeks coding 3000 fucking case statements.

---

<div class="post-metadata">

**Author:** ![MaxTheVool](https://avatars.discourse-cdn.com/v4/letter/m/9fc29f/32.png) [@MaxTheVool](https://boards.straightdope.com/u/MaxTheVool)\
**Post date:** [May 17, 2004, 7:04pm UTC](https://boards.straightdope.com/t/programmers-please-learn-when-to-not-use-while-loops/244841/80 "2004-05-17T19:04:01Z")

</div>

> [@Mtgman](#):
>
> I’m thinking there is a way to do all that within one loop using modulo arithmetic. Count high enough and have each co-ordinance determined by the remainder from a different modulus of the big number, so you get offsets. Modulus is a pretty fast operation in most languages.
> 
> Enjoy,  
> Steven

And now we’ve just gotten silly… anything that attempts to use modulo arithmetic to avoid a goto is going to make the code 30 times less legible, and far more likely to lead to errors (due to future code maintainers having no idea what in heck your modulo arithmetic is doing) than just having a goto in the first place.  
And sticking the whole loop inside a function and then doing an if off of the function result does add at least one additional branch (the if).

[Previous page](https://boards.straightdope.com/t/programmers-please-learn-when-to-not-use-while-loops/244841.md?page=3)

[Next page](https://boards.straightdope.com/t/programmers-please-learn-when-to-not-use-while-loops/244841.md?page=5)
