views:

234

answers:

4

for() or while() - which is BEST?

for (i=1; i<a; i++)
  /* do something */

OR

i=1;
while (i<a) {
/* do something */
i++;
}
+12  A: 

The first is the idiomatic way; it is what most C coders will expect to see. However, I should note that most people will also expect to see

for(i = 0; i < a; i++)

Note that the loop starts at zero. This will do something a times. If you're going to write a while loop that is equivalent to a for loop as above I strongly encourage you to write it as a for loop. Again, it is what C coders expect to see. Further, as a for loop it is easier to read as everything (initialization, loop condition, expression to be executed after each iteration) are all on one line. For the while loop they are spread out hindering readability.

Note, however, there are circumstances in which seemingly equivalent for and while loops are actually not. For example:

for(i = 0; i < 10; i++) {
    if(i == 5) continue;
    printf("%d\n", i);
}

and

i = 0;
while(i < 10) {
    if(i == 5) continue;
    printf("%d\n", i);
    i++;
}

appear at first glance to be equivalent but they are not. The for loop will print 0--9 skipping 5 on the console whereas the while loop will print 0--4 on the console and then enter an infinite loop.

Now, that handles the simple case that you asked about. What about the more complex cases that you didn't ask about? Well, it really depends but a good rule of thumb is this: if you are going to repeat something a fixed pre-determined number of times, a for loop is generally best. Otherwise, use a while loop. This is not a hard-and-fast rule but it is a good rule-of-thumb. For example, you could write

unsigned int v;
unsigned int c;
for(c = 0; v; v >>= 1) c += v & 1;

but I think most C programmers would write this as

unsigned int v;
unsigned int c;
c = 0;
while(v) { c += v & 1; v >>= 1; }

Or, as another example, if you're going to read until the end of a file then you should use a while loop. Thus

FILE *fp;
fp = fopen(path, "r");
while(fgets(buf, max, fp) != NULL) { /* something */ }

instead of

FILE *fp;
for(fp = fopen(path, "r"); fgets(buf, max, fp) != NULL; ) { /* something */ }

Now, reaching into religious territory, this is why I prefer while(1) as the right way to do an infinite loop over for(;;).

Hope that helps.

Jason
+1  A: 

Which one makes most sense in the situation.

The for loop tells you it is most probably a fixed count loop. Starting at 1 ending before a.

The while loop doesn't imply any such thing, just that it ends once i >= a (at least from just reading the while (i<a){ at the top).

Of course, this isn't a rule and programmers generally do as they see fit, but it does make it easy to read through code without having to backtrack to comprehend some section.

Dan McGrath
+3  A: 

It depends. What makes the reading most easy should be a guideline IMHO. If you know bounds beforehand you probably should use 'for'. Because it clearly says in one line where the looping starts, it ends and how to go from one element to the other.

Friedrich
+2  A: 

Vote up for Dan McG - if the loop has a fixed count, etc., use for - it's more idiomatic. Classic cases of each:

for (i = 0; i < THRESHOLD; ++i) {
  something;
}

Vs.

while (foo->next) {
  foo = foo -> next; 
}

Also: if you find yourself leaving out conditions in your for, consider what it would be like if you reworte it as a while.

At the end of the day: go back and read each version of the loop. Which one stands out more in your mind as "clear" in intent?

James