There is a (probably apocryphal) story about an industrial accident caused by a while loop testing for a sensor input being != MAX_TEMP. Unfortunately one day the sensor input went from being less than MAX_TEMP to greater than MAX_TEMP without every passing through MAX_TEMP. The process overheated without being detected, and a fire ensued. Sometimes there is a difference between != and <.
–
Charles E. GrantApr 26 '11 at 0:34

9 Answers
9

The reason to choose one or the other is because of intent and as a result of this, it increases readability.

Intent: the loop should run for as long as i is smaller than 10, not for as long as i is not equal to 10. Even though the latter may be the same in this particular case, it's not what you mean, so it shouldn't be written like that.

Readability: a result of writing down what you mean is that it's also easier to understand. For example, if you use i != 10, someone reading the code may wonder whether inside the loop there is some way i could become bigger than 10 and that the loop should continue (btw: it's bad style to mess with the iterator somewhere else than in the head of the for-statement, but that doesn't mean people don't do it and as a result maintainers expect it).

No, the loop should not run as long as i is “smaller than 10”, it should run as long as the (in this case) upper bound is not reached. When using the C++ interval / iterator range rationale, it’s far more logical to express this via != than <.
–
Konrad RudolphApr 25 '11 at 11:34

14

@Konrad I don't disagree with that at all. The main point is not to be dogmatic, but rather to choose the construct that best expresses the intent of the condition. And so, if you choose to loop through something starting at 0 and moving up, then < actually expresses that precisely.
–
DeckardApr 25 '11 at 11:36

5

@Konrad, you're missing the point. The increment operator in this loop makes it obvious that the loop condition is an upper bound, not an identity comparison. If you were decrementing, it'd be a lower bound. If you're iterating over a non-ordered collection, then identity might be the right condition.
–
Alex FeinmanApr 25 '11 at 15:56

2

@Alex the increment wasn’t my point. An interval doesn’t even necessarily have an order. It just iterates over … well, something until it reaches the end. For example, elements in a hash set. In C++, this is done using iterators and a for loop. Using < here would be silly. Also, Deckard seems to acknowledge that. I very much agree with his comment in response to mine.
–
Konrad RudolphApr 25 '11 at 16:04

1

Note, if you use a rotary buffer with chase pointers, you MUST use !=
–
SF.Jul 28 '11 at 7:19

Here's another answer that no one seems to have come up with yet. for loops should be used when you need to iterate over a sequence. Using != is the most concise method of stating the terminating condition for the loop. However, using a less restrictive operator is a very common defensive programming idiom. For integers it doesn't matter - it is just a personal choice without a more specific example. Looping over collections with iterators you want to use != for the reasons that others have stated. If you consider sequences of float or double, then you want to avoid != at all costs.

What I wanted to point out is that for is used when you need to iterate over a sequence. The generated sequence has a starting point, an interval, and a terminating condition. These are concisely specified within the for statement. If you find yourself either (1) not including the step portion of the for or (2) specifying something like true as the guard condition, then you should not be using a for loop!

The while loop is used to continue processing while a specific condition is met. If you are not processing a sequence, then you probably want a while loop instead. The guard condition arguments are similar here, but the decision between a while and a for loop should be a very conscious one. The while loop is under-appreciated in C++ circles IMO.

If you are processing a collection of items (a very common for-loop usage), then you really should use a more specialized method. Unfortunately, std::for_each is pretty painful in C++ for a number of reasons. In many cases separating the body of a for loop in a free-standing function (while somewhat painful) results in a much cleaner solution. When working with collections, consider std::for_each, std::transform, or std::accumulate. The implementation of many algorithms become concise and crystal clear when expressed in this manner. Not to mention that isolating the body of the loop into a separate function/method forces you to concentrate on the algorithm, its input requirements, and results.

If you are using Java, Python, Ruby, or even C++0x, then you should be using a proper collection foreach loop. As C++ compilers implement this feature, a number of for loops will disappear as will these types of discussions.

In the embedded world, especially in noisy environments, you can't count on RAM necessarily behaving as it should. In a conditional (for, while, if) where you compare using '==' or '!=' you always run the risk that your variables skipped that crucial value that terminates the loop--this can have disasterous consequences--Mars Lander level consequences. Using '<' or '>' in the condition provides an extra level of safety to catch the 'unknown unknowns'.

In the original example, if i were inexplicably catapulted to a value much larger than 10, the '<' comparison would catch the error right away and exit the loop, but '!=' would continue to count up until i wrapped around past 0 and back to 10.

Another related variation exists with code like for (i=4; i<length; i++) csum+=dat[i]; where legitimate packets would always have a length of at least four, but one might receive corrupted packets. If different packet types have different length requirements, one may wish to validate the length as part of the processing that's different for each packet type, but validate the checksum as part of the common logic first. If an under-length packet is received, it doesn't really matter whether the checksum computation reports "good" or "bad", but it shouldn't crash.
–
supercatAug 13 '12 at 18:11

Using "less than" is (usually) semantically correct, you really mean count up until i is no longer less than 10, so "less than" conveys your intentions clearly. Using "not equal" obviously works in virtually call cases, but conveys a slightly different meaning. In some cases this may be what you need but in my experience this has never been the case. If you really did have a case where i might be more or less than 10 but you want to keep looping until it is equal to 10, then that code would really need commenting very clearly, and could probably be better written with some other construct, such as a while loop perhaps.

One reason why I'd favour a less than over a not equals is to act as a guard. In some limited circumstances (bad programming or sanitization) the not equals could be skipped whereas less than would still be in effect.

Using (i < 10) is in my opinion a safer practice. It catches the maximum number of potential quitting cases--everything that is greater than or equal to 10. Contrast this with the other case (i != 10); it only catches one possible quitting case--when i is exactly 10.

A byproduct of this is that it improves readability. Additionally, should the increment be anything other 1, it can help minimize the likelihood of a problem should we make a mistake when writing the quitting case.

Consider:

1) for (i = 1; i < 14; i+=2)
2) for (i = 1; i != 14; i+=2)

Although both cases are likely flawed/wrong, the second is likely to be MORE wrong as it will not quit. The first case will quit, and there is a higher chance that it will quit at the right spot, even though 14 is probably the wrong number (15 would probably be better).

The first case may be right! If you want to iterate over all natural numbers less than 14, then there's no better way to to express it - calculating the "proper" upper bound (13) would be plain stupid.
–
maaartinusApr 25 '11 at 19:52

Here is one reason why you might prefer using < rather than !=. If you are using a language which has global variable scoping, what happens if other code modifies i? If you are using < rather than !=, the worst that happens is that the iteration finishes quicker: perhaps some other code increments i by accident, and you skip a few iterations in the for loop. But what happens if you are looping 0 through 10, and the loop gets to 9, and some badly written thread increments i for some weird reason. Then your loop finishes that iteration and increments i so that the value is now 11. As the loop has skipped the exit condition (i never equalled 10) it will now loop infinitely.

It doesn't necessarily have to be particularly freaky threading-and-global-variables type logic that causes this. It might just be that you are writing a loop that needs to backtrack. If you are mutating i inside the loop and you screw your logic up, having it so that it has an upper bound rather than a != is less likely to leave you in an infinite loop.

Of course, this seems like a perfect argument for for-each loops and a more functional programming style in general. But, why would you want to do that when mutable variables are so much more fun?!
–
Tom MorrisApr 25 '11 at 10:04

3

I don't think that's a terribly good reason. Either way you've got a bug that needs to be found and fixed, but an infinite loop tends to make a bug rather obvious.
–
ak2Apr 25 '11 at 13:37

In C++ the recommendation by Scott Myers in More Effective C++ (item 6) is always to use the second unless you have a reason not to because it means that you have the same syntax for iterator and integer indexes so you can swap seamlessly between int and iterator without any change in syntax.

In other languages this does not apply so I guess < is probably preferable because of Thorbjørn Ravn Andersen's point.

By the way, the other day I was discussing this with another developer and he said the reason to prefer < over != is because i might accidentally increment by more than one, and that might cause the break condition not to be met; that is IMO a load of nonsense.

"load of nonsense"... until the day you accidentially have an extra i++ in the body of the loop.
–
user1249Apr 25 '11 at 10:13

2

+1, especially for “load of nonsense”, because it is. If the loop body accidentally increments the counter, you have far bigger problems.
–
Konrad RudolphApr 25 '11 at 11:32

11

@B Tyler, we are only human, and bigger mistakes have happened before. Consider < to be more defensive programming than != then...
–
user1249Apr 25 '11 at 12:03

2

@Thorbjørn Ravn Andersen - I'm not saying that I don't agree with you, I do; < is more defensive and my colleagues hate it if I write != so I don't. However, there is a case for != in C++ and that is what I've presented.
–
user23157Apr 25 '11 at 12:48

8

One scenario where one can end up with an accidental extra i++ is when changing a while loop into a for loop. Not sure that having half the number of iterations is any better than a (near-)infinite loop though; the latter would probably make the bug more obvious.
–
ak2Apr 25 '11 at 13:33

It also allows i to modified inside the loop totally safely if need be.
–
Matthew ScharleyApr 25 '11 at 13:10

1

or if 'i' is modified totally unsafely... Another team had a weird server problem. It kept reporting 100% CPU usage and it must be a problem with the server or the monitoring system, right? No, I found a loop condition written by a 'expert senior programmer' with the same problem we're talking about.
–
jamesApr 25 '11 at 14:09

11

Except that not all C++ for loops can use <, such as iterators over a sequence, and so != would be a single common way to do loops in C++.
–
David ThornleyApr 25 '11 at 15:01

@SnOrfus: I'm not quite parsing that comment. You won't in general reliably get exceptions for incrementing an iterator too much (although there are more specific situations where you will).
–
David ThornleyApr 25 '11 at 17:00

Well, I follow the < pattern because it requires one keystroke instead of two with the > pattern, and four with !=. It's a matter of OCD-like efficiency really.
–
SpoikeAug 17 '11 at 8:17