53

I've seen both of these two for statements:

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

for(i=0;i!=10;i++)

I know they all stop when i reaches 10 , but it seems better to use the second one (I heard). What is the different?I also want to know when use iterator to access member of a vector, what is the difference between iterator condition < vec.end()and != vec.end()

Martin Ba
  • 37,187
  • 33
  • 183
  • 337
Archeosudoerus
  • 1,101
  • 9
  • 24
  • 18
    Just for the note, in for-loops, `++i` is better than `i++`, because the second one stores the former value of `i`, while the first one doesn't. – Paul Manta Nov 18 '11 at 06:19
  • From your question title the question looks really stupid but having read it it is actually a very good question. – Kevin Anthony Oppegaard Rose Nov 18 '11 at 06:20
  • 21
    @PaulManta: I would think that most modern compilers would be able to figure out that the intermediate value is unused and optimize it away. – arne Nov 18 '11 at 06:25
  • @arne - That may be harder than you expect. The compiler can't just assume that `operator++()` and `operator++(T)` are the same thing. – Brendan Long Nov 18 '11 at 06:27
  • 10
    @BrendanLong: for primitive types it can. For iterators, `++i` will be at _least_ as fast, maybe faster. – Mooing Duck Nov 18 '11 at 06:30
  • @BrendanLong: OK, but as long as no custom `operator++` are specified for the used type, I believe this should be possible. So the most common case - using `int` as a counter - should be easily optimized, because I don't think anyone would write a custom `operator++` for `int`. – arne Nov 18 '11 at 06:31
  • @Kevin Anthony Oppegaard Rose: thank you for that^_^ – Archeosudoerus Nov 18 '11 at 06:32
  • @MooingDuck - I just mean that for non-primitive types, the compiler would have to be sure that the two functions actually do the same thing. For example, I could make `i++` add one to `i` and `++i` subtract one from `i`, so it's not safe for the compiler to replace one with the other. – Brendan Long Nov 18 '11 at 06:32
  • 3
    @arne Yes, modern compilers usually do... But the 'usually' part bugs me. :) It's not like it costs me anything to always write it as `++i` and not depend on the compiler to optimize it. – Paul Manta Nov 18 '11 at 10:00
  • 2
    @PaulManta: That is a completely different story ;) I usually write `++i`, too, so that my code looks the same, regardless of the type of `i`. – arne Nov 18 '11 at 10:12
  • 1
    @BrendanLong: Actually, It's usually `{type a(*this); operator++(); return a;}`, in which case the compiler will remove the unused temprary, and it will be the same. Usually. In case it's not, I also always use `++i`. – Mooing Duck Nov 18 '11 at 16:14
  • @PaulManta for ints etc. it really doesn't make any difference. Even if compiler will not optimize the code how much longer will it take to perform the operation? Only single nanoseconds longer to push the value of eax on stack, perform "normal" increase with value storing in the variable and pop eax from stack. You only loose on the stack operation. But I have to admit that I also got use to write ++i - but this is because of my C++ experiance – SOReader Dec 07 '11 at 08:31

8 Answers8

74
for(i = start; i != end; ++i)

This is the "standard" iterator loop. It has the advantage that it works with both pointers and standard library iterators (you can't rely on iterators having operator< defined).

for(i = start; i < end; ++i)

This won't work with standard library iterators (unless they have operator< defined), but it does have the advantage that if you go past end for some reason, it will still stop, so it's slightly safer. I was taught to use this when iterating over integers, but I don't know if it's actually considered "best practice".

The way I generally write these is to prefer <.

Brendan Long
  • 53,280
  • 21
  • 146
  • 188
  • 11
    Actually, for pointers/iterators, it's only safer when iterating over part of the range. If `end` represents the end of the range, then going past `end` is **undefined behavior**, and thus all bets are off, whatever the condition. – Matthieu M. Nov 18 '11 at 07:18
  • 2
    Agreed -- the idea that it's safer is somewhat simplistic. If your loop isn't doing what you think it's doing, it's not safe. I was trying to present what I've heard as "best practice" though. – Brendan Long Nov 18 '11 at 07:19
  • Suppose someone decides to terminate your loop by setting the loop variable to the end value, rather than calling break for some reason. Then you increment the integer and compare and it is not equal... The second form has less scope for someone to mess it up accidentally, I think. – Bill Michell Nov 18 '11 at 16:57
  • @Matthieu M. - yes, going past the end is undefined behavior, but it's not impossible. Would you prefer to use `!=` and throw an exception if you go past the end? – Nathan Long Nov 18 '11 at 17:07
  • @NathanLong: My point is that if you invoke undefined behavior then whether you use `!=` or `<` does not matter since the very nature of undefined behavior is that anything can happen (the proverbial getting *demons flying out your node*). – Matthieu M. Nov 19 '11 at 13:52
12

Both will work in most situations.

If for some reason the body of code executed in the loop changes i to something greater than 10, the first version will stop looping, but the second will execute forever.

Jonathan M
  • 17,145
  • 9
  • 58
  • 91
10

My everyday practice is to use < when I iterate cycle with simple types such as integers and to use != when I work with stl-kind iterators

fat
  • 6,435
  • 5
  • 44
  • 70
7

for ( initialization ; termination condition ; iteration )

For each of those , choose youself the best one to fit your requirements, for termination condition you can use any of the binary conditional operators such as > ,< ,>= ,<= ,!=

For your given question , consider a random case in which,

for(i=0;i!=10;i++)
{
 .
 .
 i=11; //somewhere if the loop variable is changed to a value greater than 10 (this assumption is solely for demo)
 .
 .
 .
}

In this case, the loop turns out to be infinite. rather if you use a condition i<10, this works as usual. so my point is that the first approach is a bit more safer to set condition strictly.

COD3BOY
  • 11,964
  • 1
  • 38
  • 56
  • 3
    Assuming that it isn't *intentional* that setting `i` to 11 produce an infinite loop (or anyway one that continues until it sets it to 9), in which case you would use `i != 10`. Personally I don't think it's worth trying to code defensively against someone breaking your own loop invariants - either the body of the loop is supposed to modify `i` (in which case you're writing slightly gnarly code and have to be careful whatever the termination condition is), or it isn't supposed to (in which case I wouldn't bother trying to silently handle a loop body that did, since it's buggy anyway). – Steve Jessop Nov 18 '11 at 09:52
  • 4
    @Steve makes a good point. If you're worried about somebody setting i=11 inside your code so you use i<10 as your check condition... why aren't you worried about somebody just setting i=1 inside your loop causing it to run forever? – Dason Nov 18 '11 at 14:08
6

The best practice is to use != only with iterators (C++) and < otherwise. Never ever use == or != with floats/doubles. The following loop is an infinite loop:

for (double i = 0.0; i != 1.0; i += 0.1)
    printf("yes, I'm an infinite loop ;)");
SOReader
  • 5,697
  • 5
  • 31
  • 53
5

!= would allow the test to evaluate true if the value of i exceeds 10, while < would cause it to evaluate false if i exceeded 10 or merely became equal to it.

If the value of i might change within the body of the loop, this could be a consideration.

If, however, you're just looking to do something a set number of times, < is more descriptive, but either would suffice. != should, for simple step-through-10-items-and-do-grunt-work kinds of loops, be considered suboptimal in terms of being explicit about your intent.

Christopher
  • 764
  • 4
  • 6
4

I know they all stop when i reaches 10 , but it seems better to use the second one(I heard).

That is a micro optimization. Use whatever makes more sense (and above < makes more sense).

What is the different?

The 1st version uses the inequality operator !=, and the 2nd uses the less operator <.

BЈовић
  • 62,405
  • 41
  • 173
  • 273
  • 1
    Also, the second option assumes that you never increment i in the loop body. If you happen to do so you could end up in an infinite loop. Personally I agree with @VJo and think that code should express its intent first and foremost. So to me the real question is are you trying to loop only until i is 10 or whenever i is not 10? – Joshua Drake Nov 18 '11 at 14:23
1

I usually use < in for-loops for the reasons stated by others. In while-loops and more advanced for-loops though, != makes it much easier to reason about what my program does.

Say I want to find the position after the first run of '5's in an array like [5,5,5,3,5,2,3,2,0]. That is we want k such that 0 <= i < k => a[i] = 5:

int pos = 0;
// Inv: a[0..pos) = 5
while (pos != N && a[pos] == 5)
    pos = pos+1;

Once the loop has executed we know that the inverse of the loop guard is true: pos == N || a[pos] != 5. In either case we have the pos we want.

Now say we had used < in the loop guard, then all we would have known afterwards was pos >= N || a[pos] != 5, but that's not the situation we wanted to be in. Doing a lot more work, we can prove that we can't possible be in pos > N, but that seams like a waste of time compared to just using != in the loop guard.

Thomas Ahle
  • 30,774
  • 21
  • 92
  • 114