Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

With a for loop you can move the post-statement empty and move it to the bottom of the code in the loop:

for (int i = 0; i < 10; /* empty */ ) {
    //...
    ++i;
}

But in this case it doesn't gain you anything; more importantly it makes the code harder to read as you would expect the ++i to reside at the top of the statement as the post-statement.

So when is it valid to move the post-statement from its usual location to somewhere inside the loop?

EDIT: The code which made me think about this question I got from C++ Primer:

for (T* p = first_free; p != elements; /* empty */)
   alloc.destroy(--p);

Here first_free is a pointer to the first free element in an array of objects to be destroyed in reverse order, and elements is a pointer to the first object in the array. Here it seems, to me, valid to move --p from a post-statement into the loop, because otherwise you would need to rewrite the code as such:

for (T* p = first_free - 1; p != elements; --p)
   alloc.destroy(p);

Here the code would run into problems if the array doesn't actually contain any objects as you would skip over elements and thus cause a crash (or at least undefined behaviour). This means you would need an additional check before the loop whether the array actually contains any elements or not.

share|improve this question
add comment

5 Answers

The two forms are semantically identical (and you can write a for-loop as a while loop).

Use the one that makes most sense to future human readers of your program. Unless there is a good reason to, you should stay with well-known constructions, as it makes it easier to understand what your code does. Usually that good reason needs to be conveyed in a comment too, so the reader knows what the reason is.

In this particular case, the reason "just because I can" is not very good and you shouldn't.

share|improve this answer
    
+1 for considering the semantics. For the same reason, seeing people use for loops when the number of iterations is not known before looping always makes me cringe. After all, that's what while loops were designed for. Semantics do matter, IMHO. –  Schedler Apr 25 '11 at 11:16
add comment

I'd never do that. I'd just think about my termination condition again and probably use a while loop instead. Such code is a clear indicator that the termination condition is not optimal. And if you don't mess with your i variable in the body of the loop you can leave it in its head anyway.

Thus: There's no reason to write a foor-loop like that, it's just irritating.

share|improve this answer
add comment

You should always write for(int i = 0; i < end; ++i) unless you have a reason not to because:

  • Is that it easier to read and makes your intention clear.
  • By writing the increment in the for loop declaration you are giving the compiler the best possible chance to optimise the loop by unrolling it. If you increment the index inside the loop you are making it much harder for the compiler to work out if it can unroll the loop or not.

There are times when you need to increment inside the loop as your example demonstrates (that is absolutely fine), but the point is you should only do it if you can justify it.

share|improve this answer
add comment

For-loops are basically syntactic sugar for while:

for (int i = 0; i < 10; i++) { doSomething(); }

is the same as:

int i = 0; while (i < 10) { doSomething(); i++; }

(with the exception that i has a different scope)

The reason to use a for-loop is because it allows you to put everything that is important to understand the conditions surrounding the looping in one location:

  • The initialization of the iterator.
  • The condition for terminating the loop.
  • The way in which the variables related to the termination change each iteration.

This increases readability greatly. So if you're going to not adhere to this, there's basically no point in using a for-loop.

share|improve this answer
    
No, it is NOT the same. continue in a for loop will execute the post-statement, whereas continue in your "equivalent" while will skip over the increment at the end. –  zvrba Apr 25 '11 at 10:09
    
@zvrba I don't see the continue statement in the examples I give, so they are equivalent (with the exception regarding the scope I mentioned). Are you saying for-loops exist because of continue? –  Deckard Apr 25 '11 at 10:36
    
Whether your actual example has continue in it (though, I see "doSomething()" as a generic placeholder for a number of statements) is irrelevant. for() and while() have different semantics wrt. continue. Giving example like yours and not pointing out caveats is simply misleading/wrong. –  zvrba Apr 26 '11 at 6:09
    
@zvrba I understand your point and I don't disagree that they have different semantics. What I'm trying to convey is that the reason for() exists is to make it easier to organize the statements relevant in a typical while() loop. This construct then also allows an additional design decision (by the designers of the language) that makes continue-behaviour more natural. While an important design decision and important for developers to understand, it is irrelevant to the general observation (that for() is syntactic sugar for while()). –  Deckard Apr 26 '11 at 12:11
add comment

First, of course, there's the possibility that the loop body contains a break or continue which should skip that statement for some reason. (In the case of continue those paths usually ensure termination in an alternative way like incrementing by a different number or lowering the upper bound of the iteration)

Second, there's the cases where sometimes you need to do something after that statement, yet in the same iteration. For example: in C++ you might sometimes want to do something like collection.erase(iter++), but since the erase() invalidates the iterator passed in you need to do the increment first:

Collection::iterator old = iter++;
// ... possibly a condition ...
collection.erase(old);

In these cases it's usually a good idea to put the increment at the top of the loop, and only use the newly-introduced variable in the body.

There may be other edge cases, but all of them (including the ones mentioned above) should be relatively rare. In most cases there's no need for any of this and the post-statement should be in its proper place in the loop header.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.