54

All over the web, code samples have for loops which look like this:

for(int i = 0; i < 5; i++)

while I used the following format:

for(int i = 0; i != 5; ++i)

I do this because I believe it to be more efficient, but does this really matter in most cases?

Antonio
  • 19,451
  • 13
  • 99
  • 197
harryovers
  • 3,087
  • 2
  • 34
  • 56
  • 20
    I'd say that for most compiler and processors, your loop isn't any faster at all. Use the first version so that other programmers will understand the loop more readily. Now, counting down to zero _will_ help you on some processors, but you have to ask yourself if it's worth it. – Nosredna Nov 23 '09 at 15:36
  • 2
    What's the reason that you believe it to be more efficient? You're speaking in terms of running time, correct? – Benjamin Oakes Nov 23 '09 at 15:37
  • yes running would be quicker i believe but i could be very wrong – harryovers Nov 23 '09 at 15:59
  • 5
    In most languages, the first form would be more common (and there's no difference in terms of efficiency). In C++, the second form is more common, as it can be used with forward/bidirectional iterators as well as random-access ones, where the second form is only usable with random-access iterators. – jalf Nov 23 '09 at 18:20
  • Actually(notable on the Z80) doing a `!=` comparison is quicker(and smaller) than doing a `<` comparison on some platforms. Unless your writing some extremely extremely critical code though, strive to make it readable – Earlz Nov 23 '09 at 18:52
  • Counting down can be better on the 68000 series because of the dbra instruction. It's also better for JavaScript. But I'd still say go with convention unless you have a great reason not to. – Nosredna Nov 23 '09 at 18:55
  • 1
    I used to believe that if I ate my spinach I'd turn into some sort of ass-kicking machine. Turns out I was mistaken :) Profile it and find out. – Mark Simpson Dec 10 '09 at 22:37
  • 2
    @Earlz He's not writing Z80 assembly code though. If one comparison is faster than the other, the compiler will likely use the faster comparison regardless of what he codes. – David Schwartz Dec 28 '11 at 01:11
  • @DavidSchwartz that really depends on the compiler, if the complier does optimise the code then there is no need to worry about which way round this happens, but if the complier doesn't optimise the code then it is useful to know what effect the two different options would have on the compiled code. it really comes down to the compiler – harryovers Jan 10 '12 at 17:48
  • 3
    @harryovers what detail are you missing in the current answers? Lucas' answer seems very detailed. – Timothy Jones Jan 11 '12 at 00:48
  • 2
    @harryovers If performance of the loop is **that** important, you don't look around for theoretically best construct. Instead you test several versions with real world data and target compiler and use the fastest. – Tomek Szpakowicz Jan 11 '12 at 09:22
  • @TimothyJones Lucas' answer is only showing the results of a single complier, I put a bounty on the question to try and get input from some other people as there seems to be no single answer as it depends on the compiler, the question is also about the format and not the exact example ((!= or <) and (++i or i++)) as RenanGreinert points out "There is no difference for that when you are working with basic types, but when you are using a STL iterator, the preincrement is more efficient" the != / < argument is a matter of code maintenance, complier, processor and what object is being used – harryovers Jan 11 '12 at 10:17
  • @TomekSzpakowicz the question is more about what is best practise than trying to solve an exact problem – harryovers Jan 11 '12 at 10:18
  • 1
    that pre-increment looks confusing. – C.d. Jan 11 '12 at 21:32
  • 1
    @harryovers Lucas' answer shows that compiler output is irrelevant to the question of which to use, because compilers are smart enough to produce reasonably efficient code in both cases. What matters is consistency, readability, understandability and correctness of your code. – Tomek Szpakowicz Jan 12 '12 at 11:39
  • 1
    See also ["Why is != used with iterators?"](http://stackoverflow.com/questions/6673762/why-is-used-with-iterators) wherein I explain why `!=` is always preferable for loops that iterate over all the elements in a sequence in C++. – James McNellis Jan 15 '12 at 21:28
  • 2
    Why not split this into `<` vs `!=` and `++i` vs `i++`? Many answers seem to address either one or the other, but not both. – Cactus Golov Jan 15 '12 at 21:33
  • Downvoting question due to posting a bounty on a question which should be community wiki (as there is not going to be an overall best answer, because the question is mingling performance micro-optimization of C++, C, and C# inappropriately) – Tetsujin no Oni Jan 17 '12 at 15:47
  • @AntonGolov your right that is why it is so hard to select a single correct answer. – harryovers Jan 18 '12 at 11:16
  • @gnat not really a duplicate, i would say the other covers a lot less than this thread. why would you say it is a duplicate? – harryovers Jul 17 '15 at 14:51
  • agree that other question is more focused. I believe that being [less broad](http://meta.stackoverflow.com/q/258589/839601) in this case makes it good duplicate target (it would probably be even better to have this question closed as duplicate of several, better focused targets, but unfortunately system doesn't have such a feature) – gnat Jul 17 '15 at 15:19
  • i would say both are "too broard" but not duplicates – harryovers Jul 18 '15 at 09:00
  • @Deduplicator To explain the reason of my rollback: I believe that adding the phrase "Are there other good reasons?" you are changing/extending the scope/focus of the question, when the answers have already been given years ago. And indeed you need to add that question for being able to mark [the recent version](http://stackoverflow.com/questions/31455629/is-there-a-technical-reason-to-use-instead-of-when-incrementing-by-1-in) as duplicated: I don't think this is a correct procedure. – Antonio Jul 22 '15 at 21:47
  • @Antonio: This questions answers didn't restrict themselves to performance, taking a broader view even if a really *strict* reading of the question might not have demanded that. If you think I was a bit clumsy in rewording that, such happens. And yes, they are duplicates. – Deduplicator Jul 22 '15 at 22:00
  • @Deduplicator Once excluded the efficiency point of view (focus of this question), the answers to the new question go far deeper than those given for this one. I believe they are probably a good candidate for a merge, what do you think? – Antonio Jul 22 '15 at 22:20
  • @Deduplicator They go deeper on certain aspects. – Antonio Jul 22 '15 at 22:34
  • @Deduplicator One pretty original answer is here http://stackoverflow.com/a/31465421/2436175. And also this is important http://stackoverflow.com/a/31474750/2436175 – Antonio Jul 22 '15 at 22:40
  • @Antonio Ok. Make sure to highlight those two when flagging for merging, and give a very concise summary what they add. – Deduplicator Jul 22 '15 at 23:05

31 Answers31

86

Everybody loves their micro-optimizations, but this would not make a difference as far as I can see. I compiled the two variations with g++ on for Intel processors without any fancy optimizations and the results are for

for(int i = 0; i < 5; i++)
    movl $0, -12(%ebp)
    jmp L2
L3:
    leal    -12(%ebp), %eax
    incl    (%eax)
L2:
    cmpl    $4, -12(%ebp)
    jle L3

for(int i = 0; i != 5; ++i)
    movl    $0, -12(%ebp)
    jmp L7
L8:
    leal    -12(%ebp), %eax
    incl    (%eax)
L7:
    cmpl    $5, -12(%ebp)
    jne L8

I think jle and jne should translate to equally fast instructions on most architectures. So for performance, you should not distinguish between the two. In general, I would agree that the first one is a little safer and I also think more common.


EDIT (2 years later): Since this thread recently got again a lot of attention, I would like to add that it will be difficult to answer this question generally. Which versions of code are more efficient is specifically not defined by the C-Standard [PDF] (and the same applies to C++ and probably also for C# ).

Section 5.1.2.3 Program execution

§1 The semantic descriptions in this International Standard describe the behavior of an abstract machine in which issues of optimization are irrelevant.

But it is reasonable to assume that a modern compiler will produce equally efficient code and I think that in only very rare cases will the loop-test and the counting expression be the bottleneck of a for-loop.

As for taste, I write

for(int i = 0; i < 5; ++i)
Student
  • 805
  • 1
  • 8
  • 11
Lucas
  • 13,679
  • 13
  • 62
  • 94
  • @harryovers: I have to say, that I wouldn't be confused by your way. I think it is pretty obvious what is going on, but you shouldn't get to worked up about small optimizations, if you don't have a performance issue. – Lucas Nov 23 '09 at 16:04
  • i'm not really worried about it i just wanted to know what thoughts people had – harryovers Nov 23 '09 at 16:20
  • 6
    The important part of this is that x86 uses a condition code register, so it computes both equality and sign flags for any comparison, so conditional jumps for all integral in/equalities take exactly the same amount of time. – Ken Nov 23 '09 at 19:09
69

If for some reason i jumps to 50 in the loop, your version would loop forever. The i < 5 is a sanity check.

Yuriy Faktorovich
  • 67,283
  • 14
  • 105
  • 142
  • 18
    If i is being modified in the loop, things are bad enough that I'd probably _rather_ have an infinite loop to help me track down what's going on. Seriously, if something is messing with i, there should be an assert in the loop to find out. Another reason I prefer languages that let me do a foreach instead of a for whenever possible. – Nosredna Nov 23 '09 at 15:34
  • Is it really that bad? What if someone wants to break out of the loop after its finished? Setting i to int.MaxValue would do the trick without refactoring. – Yuriy Faktorovich Nov 23 '09 at 15:36
  • 12
    Setting i to break out of the loop? Ugh. If _break_ doesn't work to do that, refactor! – Nosredna Nov 23 '09 at 15:38
  • @Yuriy Faktorovich: So would `break;` – Will Eddins Nov 23 '09 at 15:39
  • what about a normal break instead of setting the iterator to int.MaxValue? – RvdK Nov 23 '09 at 15:41
  • 4
    Thats my point, what if it figures out that it needs to exit in some business logic at the beginning of the clause. break; wouldn't execute the remaining logic. – Yuriy Faktorovich Nov 23 '09 at 15:42
  • Although at that point, Nosredna is likely right, refactoring may be in order. – Yuriy Faktorovich Nov 23 '09 at 15:43
  • Except that C, C#, and C++ all have `break;`. – David Thornley Nov 23 '09 at 18:52
  • @Yuriy. For that case, adding a boolean flag would be clearer than altering i. – Nosredna Nov 23 '09 at 18:58
  • break; won't work properly in a nested loop, will it? : `for (int i = 0; i < 10; ++i) { for (int j = 0; j < 10; ++j) { if (someCondition) { i = 10; break; /* how else can I break out of the outer loop here? */ } }` – Bill Nov 23 '09 at 19:49
  • 1
    @Bill you gotta use goto statements(It is great to say "using goto is the right way", very rarely do I get that ability). – Yuriy Faktorovich Nov 23 '09 at 20:43
  • 2
    The `<` version over the `!=` can make it easier to write loop invariants for proving correctness. – caf Nov 24 '09 at 00:58
  • 1
    +1 from me, regardless of whether modifying the loop variable is right or wrong. More defensive. – ta.speot.is Jan 14 '12 at 06:06
  • +1 See http://blogs.csoonline.com/node/151 for how `!=` test can turn small bugs to bigger bugs. Use `<` where possible. – Yakov Galka Jan 15 '12 at 22:28
41

The form

for (int i = 0; i < 5; i++)

is idiomatic, so it's easier to read for experienced C programmers. Especially when used to iterate over an array. You should write idiomatic code whenever possible as it reads faster.

It is also a little safer in situations when you modify i inside the loop or use an increment different then 1. But it's a minor thing. It's best to carefully design your loop and add some asserts to catch broken assumptions early.

Tomek Szpakowicz
  • 14,063
  • 3
  • 33
  • 55
  • 13
    The form `for (int i = 0; i != 5; ++i)` would be more idiomatic to quite a few C++ people. Really though, I can't how you could say that either is not idiomatic in any C-style language, they're both mother's knee stuff in all those languages. – Jon Hanna Jan 11 '12 at 17:38
  • @JonHanna As for 2nd part of your comment: I learned C from K&R and this is the version that I've since seen used the most. And I find it the most readable at a glance. As for 1st part: Do you mean that for loop with C++ iterators looks like this: `for (some::long_iter_type it = begin; it != end; ++it) ...`? If so then: a) We are talking of C code, mostly. b) Even in C++ `int i` is not an iterator. – Tomek Szpakowicz Jan 12 '12 at 11:44
  • 2
    We're not talking C code, the question quite explicitly includes C++ and C# and implicitly Java and Javascript. Integers are not iterators, but the use of them can lead to != being more instinctive than <. I still can't consider either more idiomatic in any of those languages though, they're all forms where you should grok all of them as natural in any of those languages. – Jon Hanna Jan 12 '12 at 12:04
  • @JonHanna Right. You've got me on the languages part. But still the basic idioms of iterating over integer range comes from C. And here I don't see how `!=` would ever be considered intuitive. Maybe I did too much math in my life but for me it's either `<` or `<=`---as in `0 <= i < n` or `0 <= i <= n-1`---and I prefer the former. – Tomek Szpakowicz Jan 13 '12 at 14:23
  • 3
    +2 for talking about the real point (readability, not performance) and for the word "idiomatic". The word finally lets me express simply this idea I had - that the two idiomatic `for` statements are `for (int i=0; inext)`. I think one should prefer these two whenever possible. – ugoren Jan 14 '12 at 20:18
18

If the increment rule changes slightly you immediately have an infinite loop. I much prefer the first end condition.

Chris Ballance
  • 33,810
  • 26
  • 104
  • 151
13

It depends on the language.

C++ texts often suggest the second format as that will work with iterators which can be compared (!=) directly but not with a greater to or less than condition. Also pre increment can be faster than post increment as there is no need for a copy of the variable for comparison - however optimisers can deal with this.

For integers either form works. The common idiom for C is the first one whilst for C++ it is the second.

For C# and Java use I would foreach to loop over all things.

In C++ there is also the std::for_each function requiring a use of a functor which for simple cases is probably more complex than either example here and the Boost FOR_EACH which can look like the C# foreach but is complex inside.

mmmmmm
  • 32,227
  • 27
  • 88
  • 117
  • While I agree, the OP is trying to micro optimize by distinguishing a `!=` and a `<` call, so I doubt they'd want to introduce the overhead of an iterator for a foreach call! – weston Jan 17 '12 at 13:03
12

With regards to using ++i instead of i++, it doesn't make a difference with most compilers, however ++i could be more efficient than i++ when used as an iterator.

Calum
  • 1,889
  • 2
  • 18
  • 36
  • 1
    Agreed. Software such as 'cppcheck' actually warn you when you use a post increment instead of a pre increment on an iterator. – Trevor Hickey Jan 12 '12 at 04:49
10

There's actually four permutations on what you give. To your two:

for(int i = 0; i < 5; i++)
for(int i = 0; i != 5; ++i)

We can add:

for(int i = 0; i < 5; ++i)
for(int i = 0; i != 5; i++)

On most modern machines with modern compilers it shouldn't be surprising that these will be of exactly the same efficiency. It could be just about possible that you may one day find yourself programming for some small processor where there's a difference between equality comparisons and less-than comparisons.

It may in some case make more sense to a particular mind with a particular case to think of "less than" or of "not equals" depending on the reason why we chose 0 and 5, but even then what makes one seem obvious to one coder may not with another.

More abstractly, these are of the forms:

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

An obvious difference here is that in two cases someType must have a meaning for < and for the rest it must have a meaning for !=. Types for which != is defined and < isn't are quite common, including quite a few iterator objects in C++ (and potentially in C# where the same approach as STL iterators is possible and sometimes useful, but neither as idiomatic, directly supported by common libraries nor as often useful since there are rival idioms with more direct support). It's worth noting that the STL approach is specifically designed so as to include pointers within the set of valid iterator types. If you're in the habit of using the STL you'll consider the forms with != far more idiomatic even when applied to integers. Personally a very tiny amount of exposure to it was enough to make it my instinct.

On the other hand, while defining < and not != would be rarer, it's applicable to cases where either we replace the increment with a different increase in i's value, or where i may be altered within the loop.

So, there's definite cases on both sides where one or the other is the only approach.

Now for ++i vs i++. Again with integers and when called directly rather than through a function that returns the result (and chances are even then) the practical result will be exactly the same.

In some C-style languages (those without operator over-loading) integers and pointers are about the only cases there is. We could just about artificially invent a case where the increment is called through a function just to change how it goes, and chances are the compiler will still turn them into the same thing anyway.

C++ and C# allow us to override them. Generally the prefix ++ operates like a function that does:

val = OneMoreThan(val);//whatever OneMoreThan means in the context.
//note that we assigned something back to val here.
return val;

And the postfix ++ operates like a function that does:

SomeType copy = Clone(val);
val = OneMoreThan(val);
return copy;

Neither C++ nor C# match the above perfectly (I quite deliberately made my pseudo-code match neither), but in either case there may be a copy or perhaps two made. This may or may not be expensive. It may or may not be avoidable (in C++ we often can avoid it entirely for the prefix form by returning this and in the postfix by returning void). It may or may not be optimised away to nothing, but it remains that it could be more efficient to do ++i than i++ in certain cases.

More particularly, there's the slight possibility of a slight performance improvement with ++i, and with a large class it could even be considerable, but barring someone overriding in C++ so that the two had completely different meanings (a pretty bad idea) it's not generally possible for this to be the other way around. As such, getting into the habit of favouring prefix over postfix means you might gain an improvement mayone one time in a thousand, but won't lose out, so it's a habit C++ coders often get into.

In summary, there's absolutely no difference in the two cases given in your question, but there can be in variants of the same.

Jon Hanna
  • 110,372
  • 10
  • 146
  • 251
9

I switched to using != some 20+ years ago after reading Dijkstra's book called "A Discipline of Programming". In his book Dijkstra observed that weaker continuation conditions lead to stronger post-conditions in loop constructs.

For example, if we modify your construct to expose i after the loop, the post-condition of the fist loop would be i >= 5, while the post-condition of the second loop is a much stronger i == 5. This is better for reasoning about the program in formal terms of loop invariants, post-conditions, and weakest pre-conditions.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
6

I agree with what's been said about readability - it's important to have code that's easy for a maintainer to read, although you'd hope that whoever that is would understand both pre- and post-increments.

That said, I thought that I'd run a simple test, and get some solid data about which of the four loops runs fastest. I'm on an average spec computer, compiling with javac 1.7.0.

My program makes a for loop, iterating 2,000,000 time over nothing (so as not to swamp the interesting data with how long it takes to do whatever is in the for loop). It use all four types proposed above, and times the results, repeating 1000 times to get an average.

The actual code is:

public class EfficiencyTest
{
public static int iterations = 1000;

public static long postIncLessThan() {
    long startTime = 0;
    long endTime = 0;
    startTime = System.nanoTime();
    for (int i=0; i < 2000000; i++) {}
    endTime = System.nanoTime();
    return endTime - startTime;
}

public static long postIncNotEqual() {
    long startTime = 0;
    long endTime = 0;
    startTime = System.nanoTime();
    for (int i=0; i != 2000000; i++) {}
    endTime = System.nanoTime();
    return endTime - startTime;
}

public static long preIncLessThan() {
    long startTime = 0;
    long endTime = 0;
    startTime = System.nanoTime();
    for (int i=0; i < 2000000; ++i) {}
    endTime = System.nanoTime();
    return endTime - startTime;
}

public static long preIncNotEqual() {
    long startTime = 0;
    long endTime = 0;
    startTime = System.nanoTime();
    for (int i=0; i != 2000000; ++i) {}
    endTime = System.nanoTime();
    return endTime - startTime;
}

public static void analyseResults(long[] data) {
    long max = 0;
    long min = Long.MAX_VALUE;
    long total = 0;
    for (int i=0; i<iterations; i++) {
        max = (max > data[i]) ? max : data[i];
        min = (data[i] > min) ? min : data[i];
        total += data[i];
    }
    long average = total/iterations;

    System.out.print("max: " + (max) + "ns, min: " + (min) + "ns");
    System.out.println("\tAverage: " + (average) + "ns");
}

public static void main(String[] args) {
    long[] postIncLessThanResults = new long [iterations];
    long[] postIncNotEqualResults = new long [iterations];
    long[] preIncLessThanResults = new long [iterations];
    long[] preIncNotEqualResults = new long [iterations];

    for (int i=0; i<iterations; i++) {
        postIncLessThanResults[i] = postIncLessThan();
        postIncNotEqualResults[i] = postIncNotEqual();
        preIncLessThanResults[i] = preIncLessThan();
        preIncNotEqualResults[i] = preIncNotEqual();
    }
    System.out.println("Post increment, less than test");
    analyseResults(postIncLessThanResults);

    System.out.println("Post increment, inequality test");
    analyseResults(postIncNotEqualResults);

    System.out.println("Pre increment, less than test");
    analyseResults(preIncLessThanResults);

    System.out.println("Pre increment, inequality test");
    analyseResults(preIncNotEqualResults);
    }
}

Sorry if I've copied that in wrong!

The results supprised me - testing i < maxValue took about 1.39ms per loop, whether using pre- or post-increments, but i != maxValue took 1.05ms. That's a that's either a 24.5% saving or a 32.5% loss of time, depending on how you look at it.

Granted, how long it takes a for loop to run probably isn't your bottleneck, but this is the kind of optimisation that it's useful to know about, for the rare occasion when you need it.

I think I'll still stick to testing for less than, though!

Edit

I've tested decrementing i as well, and found that this doesn't really have an effect on th time it takes - for (int i = 2000000; i != 0; i--) and for (int i = 0; i != 2000000; i++) both take the same length of time, as do for (int i = 2000000; i > 0; i--) and for (int i = 0; i < 2000000; i++).

DenverCoder8
  • 401
  • 7
  • 15
  • are you implying that compiling with javac 1.7.0 will optimize pre & post increments in loops but not the end condition – harryovers Jan 18 '12 at 11:20
  • I also ran some test using a slightly modified version of the same code in C# & .NET4 and the results suggest that the compiler will optimize the loop no matter what format is used as there was less than 0.05ms between all of them – harryovers Jan 18 '12 at 11:41
  • @harryovers Yes, that's exactly what my results showed. I ran it several times, and each run gave the same result (to experimental error). – DenverCoder8 Jan 18 '12 at 12:35
  • Sorry, that was ambiguous - I was agreeing to your first comment. What you found with C# and .NET is what I expected to find - that the compiler realised they were all the same! – DenverCoder8 Jan 18 '12 at 13:18
  • It certainly would be interesting to see how different languages and compilers compared when running fundamentally the same code – harryovers Jan 18 '12 at 16:58
4

I would never do this:

for(int i = 0; i != 5; ++i)

i != 5 leaves it open for the possibility that i will never be 5. It's too easy to skip over it and run into either an infinite loop or an array accessor error.

++i

Although a lot of people know that you can put ++ in front, there are a lot of people who don't. Code needs to be readable to people, and although it could be a micro optimization to make the code go faster, it really isn't worth the extra headache when someone has to modify the code and figure why it was done.

I think Douglas Crockford has the best suggestion and that is to not use ++ or -- at all. It can just become too confusing (may be not in a loop but definitely other places) at times and it is just as easy to write i = i + 1. He thinks it's just a bad habit to get out of, and I kind of agree after seeing some atrocious "optimized" code.

I think what crockford is getting at is with those operators you can get people writing things like:

var x = 0;
var y = x++;

y = ++x * (Math.pow(++y, 2) * 3) * ++x;

alert(x * y);

//the answer is 54 btw.

kemiller2002
  • 113,795
  • 27
  • 197
  • 251
  • i feel that appropriate comments in the code make it a lot easier to read than the syntax but that said a lot of people will still look at it and be confused as why it has been done this way – harryovers Nov 23 '09 at 15:47
  • 13
    I can't disagree with you more. I expect that knowing prefix vs postfix increment is among the absolute minimum of knowledge that I would accept for a maintenance programmer. I think it should be used when it can be, because it's very easy to mistype i = i + 1 in a way that the compiler won't catch. – rmeador Nov 23 '09 at 16:02
  • @rmeador don't get me wrong, I totally agree with you that they should know it. My problem is that I can't code for what I think should be, I have to code for what is. I will say there are other times too where trying to be terse leads to possible assumptions that aren't correct. Mostly these are stupid things that taking up 2 lines instead of 1 would have become evident. Little stupid mistakes that could have been avoided. – kemiller2002 Nov 23 '09 at 16:22
  • 14
    If people don't understand ++i, they have no business writing code. – jalf Nov 23 '09 at 18:23
  • @jalf whether or not you think that is true, there are people who still get tripped up by that. – kemiller2002 Nov 23 '09 at 18:35
  • 5
    Your advice doesn't apply well to C++, because there are situations in C++ when you very definitely want `for (i = ...; i != ...; ++i)`, if `i` is not a random-access iterator and/or `i` is fairly complicated. It's useful to develop good habits rather than miss something and code something improperly. – David Thornley Nov 23 '09 at 18:59
  • I assumed people learned pre- and post-incrementing at the same time. But maybe not. Post-incrementing is much more common, so I suppose someone who learns by reading code may be familiar with one and not the other. By the way, Crockford's probably right for the cases where pre- and post-incrementing are used in a complex expression. Personally, I turn that pickiness off in jsLint. i++ sitting all alone should not be confusing to anyone. – Nosredna Nov 23 '09 at 19:01
  • whether you use `i++` or `++i` makes no difference, It only matters when you are assigning something to `i++` as the variable will be assigned to `i` before incrementation. – Joseph Le Brech Jan 11 '12 at 15:20
  • 2
    I'd have thought `++i` would be more common than `i++` if only because in those cases where it makes a difference - you use the value as part of a wider expression - one is slightly more likely to care about the new value than the old. – Jon Hanna Jan 11 '12 at 17:35
  • 8
    The behavior of `y = ++x * (Math.pow(++y, 2) * 3) * ++x;` is undefined; it modifies `x` twice without an intervening sequence point. And if I see `i = i + 1;` in C code, my first thought is that the author hasn't learned the language. – Keith Thompson Jan 12 '12 at 04:09
  • "It's too easy to skip over it and run into either an infinite loop or an array accessor error." That's exactly what you _want_, since an infinite loop or access violation will help you detect the error sooner. If the loop index or iterator isn't hitting the stop value precisely, there's probably something going wrong or at least something you don't understand about the code. (Floating point excepted.) – Adrian McCarthy Dec 18 '15 at 19:57
4

In generic code you should prefer the version with != operator since it only requires your i to be equally-comparable, while the < version requires it to be relationally-comparable. The latter is a stronger requirement than the former. You should generally prefer to avoid stronger requrements when a weaker requirement is perfectly sufficient.

Having said that, in your specific case if int i both will work equally well and there won't be any difference in performance.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
4

It is not a good idea to care about efficiency in those cases, because your compiler is usually smart enough to optimize your code when it is able to.

I have worked to a company that produces software for safety-critical systems, and one of the rules was that the loop should end with a "<" instead of a !=. There are several good reasons for that:

  1. Your control variable might jump to a higher value by some hw problem or some memory invasion;

  2. In the maintenance, one could increment your iterator value inside the loop, or do something like "i += 2", and this would make your loop to roll forever;

  3. If for some reason your iterator type changes from "int" to "float" (I don't know why someone would do that, but anyways...) an exact comparison for float points is a bad practice.

(The MISRA C++ Coding Standard (for safety-critical systems) also tell you to prefer the "<" instead of "!=" in the rule 6-5-2. I don't know if I can post the rule definition here because MISRA is a paid document.)

About the ++i or i++, I'd preffer to use ++i. There is no difference for that when you are working with basic types, but when you are using a STL iterator, the preincrement is more efficient. So I always use preincrement to get used to it.

Renan Greinert
  • 3,376
  • 3
  • 19
  • 29
4

I have decided to list the most informative answers as this question is getting a little crowded.

DenverCoder8's bench marking clearly deserves some recognition as well as the compiled versions of the loops by Lucas. Tim Gee has shown the differences between pre & post increment while User377178 has highlighted some of the pros and cons of < and !=. Tenacious Techhunter has written about loop optimizations in general and is worth a mention.

There you have my top 5 answers.

  1. DenverCoder8
  2. Lucas
  3. Tim Gee
  4. User377178
  5. Tenacious Techhunter
Community
  • 1
  • 1
harryovers
  • 3,087
  • 2
  • 34
  • 56
3

For the record the cobol equivalent of the "for" loop is:-

    PERFORM VARYING VAR1 
            FROM +1 BY +1
            UNTIL VAR1 > +100
  *      SOME VERBOSE COBOL STATEMENTS HERE
    END-PERFORM.

or

PERFORM ANOTHER-PARAGRAPH
        VARYING VAR2 BY +1 
        UNTIL TERMINATING-CONDITION
        WITH TEST AFTER.

There are many variations on this. The major gotcha for peoples whose minds have not been damaged by long exposure to COBOL is the, by default, UNTIL actually means WHILE i.e. the test is performed at the top of the loop, before the loop variable is incremented and before the body of the loop is processed. You need the "WITH TEST AFTER" to make it a proper UNTIL.

James Anderson
  • 27,109
  • 7
  • 50
  • 78
2

The second is less readable, I think (if only because the "standard" practice seems to be the former).

MoominTroll
  • 2,502
  • 21
  • 24
2

Numeric literals sprinkled in your code? For shame...

Getting back on track, Donald Knuth once said

We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil.

So, it really boils down to which is easier to parse

So... taking into account both of the above, which of the following is easier for a programmer to parse?

for (int i = 0; i < myArray.Length; ++i)

for (int i = 0; i != myArray.Length; ++i)

Edit: I'm aware that arrays in C# implement the System.Collections.IList interface, but that's not necessarily true in other languages.

Powerlord
  • 87,612
  • 17
  • 125
  • 175
  • Why would you iterate one time less in the second example? – UncleBens Nov 23 '09 at 16:13
  • 1
    i wouldn't do "i != myArray.Length - 1". i'd prefer "i = 0, n = myArray.Length; i != n" – harryovers Nov 23 '09 at 16:15
  • Good answer. Of course, we don't know that he's going through an entire array. In fact, with that numeric literal in there we have no idea what he's doing. – Nosredna Nov 23 '09 at 16:23
  • This is a case where counting down can be faster, depending how fast getting the length of an array is. – Nosredna Nov 23 '09 at 16:26
  • @UncleBens: You wouldn't. Braino on my part. – Powerlord Nov 23 '09 at 16:29
  • @Nosredna, why can't a compiler optimize out finding the length of the array? Most compilers can figure out if the length of the array can change within the loop. – tster Dec 10 '09 at 22:49
  • @Nosredna the point is about the format i use, in this case it would probably make no difference but in the case of a collection where to get the size a count of all the elements would be required it would be quicker as it is not counting every time. the question boils down to if one format is used for every for loop no matter what object is used as the iterator then which option is faster, when either is used with ints there would be no difference but if it was an object i had written then there could be massive differences – harryovers Jan 11 '12 at 10:24
  • @harryovers: Actually, in this case, your version ends up slower, because the compiler isn't smart enough to eliminate the bounds check. – porges Jan 17 '12 at 02:58
2

Regarding readability. Being a C# programmer who likes Ruby, I recently wrote an extension method for int which allows the following syntax (as in Ruby):

4.Times(x => MyAction(x));
Martin R-L
  • 4,039
  • 3
  • 28
  • 28
2

To sum up pros and cons of both options

Pros of !=

  • when int is replaced with some iterator or a type passed via template argument there is better chance it will work, it will do what is expected and it will be more efficient.
  • will 'loop forever' if something unpredicted happens to the i variable allowing bug detection

Pros of <

  • as other say is as efficient as the other one with simple types
  • it will not run 'forever' if i is increased in the loop or 5 is replaced with some expression that gets modified while the loop is running
  • will work with float type
  • more readable - matter of getting used to

My conclusions:

  1. Perhaps the != version should be used in majority of cases, when i is discrete and it is as well as the other side of the comparison is not intended to be tampered within the loop.

  2. While the presence of < would be a clear sign that the i is of simple type (or evaluates to simple type) and the condition is not straightforward: i or condition is additionally modified within the loop and/or parallel processing.

user377178
  • 2,363
  • 3
  • 16
  • 11
  • 1
    Not sure about the bug detection properties of getting stuck in an infinite loop. Not that carrying on regardless is any better. So maybe after the loop `Assert(i==length-1);` if that is a concern. – weston Jan 17 '12 at 16:51
2

It appears no one has stated the reason why historically the preincrement operator, ++i, has been preferred over the postfix i++, for small loops.

Consider a typical implementation of the prefix (increment and fetch) and the postfix (fetch and increment):

// prefix form: increment and fetch
UPInt& UPInt::operator++()
{
   *this += 1;      // increment
   return *this;    // fetch
}

// posfix form: fetch and increment
const UPInt UPInt::operator++(int)
{
   const UPInt oldValue = *this;
   ++(*this);
   return oldValue;
} 

Note that the prefix operation can be done in-place, where as the postfix requires another variable to keep track of the old value. If you are not sure why this is so, consider the following:

int a = 0;
int b = a++; // b = 0, the old value, a = 1 

In a small loop, this extra allocation required by the postfix could theoretically make it slower and so the old school logic is the prefix is more efficient. As such, many C/C++ programmers have stuck with the habit of using the prefix form.

However, noted elsewhere is the fact that modern compilers are smart. They notice that when using the postfix form in a for loop, the return value of the postfix is not needed. As such, it's not necessary to keep track of the old value and it can be optimized out - leaving the same machine code you would get from using the prefix form.

Tim Gee
  • 1,062
  • 7
  • 9
1

FORTRAN's DO loop and BASIC's FOR loop implemented < (actually <=) for positive increments. Not sure what COBOL did, but I suspect it was similar. So this approach was "natural" to the designers and users of "new" languages like C.

Additionally, < is more likely than != to terminate in erroneous situations, and is equally valid for integer and floating point values.

The first point above is the probable reason the style got started, the second is the main reason it continues.

Hot Licks
  • 47,103
  • 17
  • 93
  • 151
1

Well... that's fine as long as you don't modify i inside your for loop. The real "BEST" syntax for this entirely depends on your desired result.

Chris Ballance
  • 33,810
  • 26
  • 104
  • 151
Nathan Wheeler
  • 5,896
  • 2
  • 29
  • 48
1

If your index were not an int, but instead (say) a C++ class, then it would be possible for the second example to be more efficient.

However, as written, your belief that the second form is more efficient is simply incorrect. Any decent compiler will have excellent codegen idioms for a simple for loop, and will produce high-quality code for either example. More to the point:

  • In a for loop that's doing heavy performance-critical computation, the index arithmetic will be a nearly negligible portion of the overall load.

  • If your for loop is performance-critical and not doing heavy computation such that the index arithmetic actually matters, you should almost certainly be restructuring your code to do more work in each pass of the loop.

Stephen Canon
  • 103,815
  • 19
  • 183
  • 269
1

When I first started programming in C, I used the ++i form in for loops simply because the C compiler I was using at the time did not do much optimization and would generate slightly more efficient code in that case.

Now I use the ++i form because it reads as "increment i", whereas i++ reads as "i is incremented" and any English teacher will tell you to avoid the passive voice.

The bottom line is do whatever seems more readable to you.

Ferruccio
  • 98,941
  • 38
  • 226
  • 299
1

I think in the end it boils down to personal preference.
I like the idea of

for(int i = 0; i < 5; i++)

over

for(int i = 0; i != 5; ++i)

due to there being a chance of the value of i jumping past 5 for some reason. I know most times the chances on that happening are slim, but I think in the end its good practice.

ixron
  • 127
  • 2
  • 11
1

We can use one more trick for this.

for (i = 5; i > 0; i--)

I suppose most of the compilers optimize the loops like this. I am not sure. Someone please verify.

ChandanK
  • 607
  • 7
  • 10
  • Are you saying you think that is more optimal? And that a compiler would take a `for (i = 0; i < 5; i++)` and replace with that? – weston Jan 17 '12 at 12:58
  • Well if `i` was being used to index into an array (for example), then your loop would be reversed. No compiler would do this. However if `i` is not referenced inside the for loop (or after it), I guess it would be up to the compiler. For fixed iteration loops like this however compilers often have the option to unroll them. i.e. in this case it would copy and paste the inner code 5 times rather than looping. It's a trade off between code size and speed that is often customisable in your compiler. – weston Jan 17 '12 at 16:36
1

Ultimately, the deciding factor as to what is more efficient is neither the language nor the compiler, but rather, the underlying hardware. If you’re writing code for an embedded microcontroller like an 8051, counting up vs. counting down, greater or less than vs. not equals, and incrementing vs. decrementing, can make a difference to performance, within the very limited time scale of your loops.

While sufficient language and compiler support can (and often do) mitigate the absence of the instructions required to implement the specified code in an optimal but conceptually equivalent way, coding for the hardware itself guarantees performance, rather than merely hoping adequate optimizations exist at compile time.

And all this means, there is no one universal answer to your question, since there are so many different low-end microcontrollers out there.

Of much greater importance, however, than optimizing how your for loop iterates, loops, and breaks, is modifying what it does on each iteration. If causing the for loop one extra instruction saves two or more instructions within each iteration, do it! You will get a net gain of one or more cycles! For truly optimal code, you have to weigh the consequences of fully optimizing how the for loop iterates over what happens on each iteration.

All that being said, a good rule of thumb is, if you would find it a challenge to memorize all the assembly instructions for your particular target hardware, the optimal assembly instructions for all variations of a “for” loop have probably been fully accounted for. You can always check if you REALLY care.

1

I see plenty of answers using the specific code that was posted, and integer. However the question was specific to 'for loops', not the specific one mentioned in the original post.

I prefer to use the prefix increment/decrement operator because it is pretty much guaranteed to be as fast as the postfix operator, but has the possibility to be faster when used with non-primitive types. For types like integers it will never matter with any modern compiler, but if you get in the habit of using the prefix operator, then in the cases where it will provide a speed boost, you'll benefit from it.

I recently ran a static analysis tool on a large project (probably around 1-2 million lines of code), and it found around 80 cases where a postfix was being used in a case where a prefix would provide a speed benefit. In most of these cases the benefit was small because the size of the container or number of loops would usually be small, but in other cases it could potentially iterate over 500+ items.

Depending on the type of object being incremented/decremented, when a postfix occurs a copy can also occur. I would be curious to find out how many compilers will spot the case when a postfix is being used when its value isn't referenced, and thus the copy could not be used. Would it generate code in that case for a prefix instead? Even the static analysis tool mentioned that some of those 80 cases it had found might be optimized out anyway, but why take the chance and let the compiler decide? I don't find the prefix operator to be at all confusing when used alone, it only becomes a burden to read when it starts getting used, inline, as part of a logic statement:

int i = 5;
i = ++i * 3;

Having to think about operator precedence shouldn't be necessary with simple logic.

int i = 5;
i++;
i *= 3;

Sure the code above takes an extra line, but it reads more clearly. But with a for loop the variable being altered is its own statement, so you don't have to worry about whether it's prefix or postfix, just like in the code block above, the i++ is alone, so little thought is required as to what will happen with it, so this code block below is probably just as readable:

int i = 5;
++i;
i *= 3;

As I've said, it doesn't matter all that much, but using the prefix when the variable is not being used otherwise in the same statement is just a good habit in my opinion, because at some point you'll be using it on a non-primitive class and you might save yourself a copy operation.

Just my two cents.

Nic Foster
  • 2,864
  • 1
  • 27
  • 45
  • In C/C++ "i = ++i * 3" is actually undefined - you are modifying the variable 'i' twice without an intervening sequence point. – jakobbotsch Jan 17 '12 at 17:51
  • Interesting, guess that reinforces the point then. I assumed the ++ would occur first since it has a higher precedence, and then the multiply. – Nic Foster Jan 18 '12 at 04:19
1

On many architectures, it is far easier to check whether something is zero that whether it is some other arbitrary integer, therefore if you truly want to optimize the heck out of something, whenever possible count down, not up (here's an example on ARM chips).

In general, it really depends on how you think about numbers and counting. I'm doing lots of DSP and mathematics, so counting from 0 to N-1 is more natural to me, you may be different in this respect.

Phonon
  • 12,549
  • 13
  • 64
  • 114
1

I remember one code segment where the i was getting incremented by 2 instead of 1 due to some mistake and it was causing it to go in infinite loop. So it is better to have this loop as shown in the first option. This is more readable also. Because i != 5 and i < 5 conveys two different meaning to the reader. Also if you are increasing the loop variable then i<5 is suppose to end some point of time while i != 5 may never end because of some mistake.

Braj Kishore
  • 351
  • 2
  • 11
0

It is not good approach to use as != 5. But

for (int i =0; i<index; ++i)

is more efficient than

for(int i=0; i<index; i++)

Because i++ first perform copy operation. For detailed information you can look operator overloading in C++.

oldTimes
  • 259
  • 3
  • 4
  • 13
  • 3
    The result of the third expression is discarded, so there shouldn't be any difference in performance; the compiler should recognize that it only needs the side effect. I'd expect the same generated code for both, at least if optimization is enabled. (That doesn't apply if you're calling an overloaded "++" operator.) – Keith Thompson Jan 12 '12 at 04:06
0

There is actually an even more “historical” reason which predates the C++ example provided by Tim Gee: the mechanism originated in C on a machine that had pre- and post-increment register instructions and the C language was originally intended to make “coding to the machine” more easily maintainable than using assembly language.

While it is true that many current compilers can frequently elide any extra copies, it is always best to learn the language and choose action based on your specific environment and requirements rather than simply blindly follow others’ examples.

For what it’s worth, I would define the loop index as unsigned rather than int because it better defines the valid domain of a simple loop counter and will protect you if the value of i ever becomes negative…

In the case of C in particular, the foundation language referenced, the ordering comparator made sense because of the safety it provided and because the machine was optimized for doing register (integer) value comparisons, but it also came into practice primarily because of the idiom to use zero-based array indices.

Using i != length was actually a bug, since you would need to code i != (length - 1). This would of course be very inefficient because you would either need to precompute and store (length - 1) in a temporary variable, thus “wasting” a precious register resource, or you would end up recalculating it in the loop comparator every time — an even worse faux pas!

More to the point, I am answering this because I think a “bonus” for the “best” answer to this question is rather pointless. It is important to avoid trying to define “global” solutions based on topics which have frequently been the topic of “flame wars” or “religious wars” as they used to be called in forums. Why?

If you spend even a cursory amount of time researching template-idioms in C++ or generics in C# and Java, you will learn that the ordering and equality comparators are not always fundamental. It is quite common to define the (in)equality operators in terms of the ordering operators since they are typically necessary for using STL or generic containers. In those environments it is simply dangerous to assume that you can define the “most efficient” source syntax to be used across all languages derived from the C base and you must carefully decide which comparison(s) to use when you take advantage of predefined algorithms.

The “change” in syntax for iterator loops was based on the desire to have the same syntax for all iterators, and the ordering comparators simply wouldn’t work for anything but array pointers masquerading as iterators — that is the only scenario where consecutively accessed elements of a container are guaranteed to be stored in contiguous memory with monotonically increasing addresses.

If efficiency really matters to you, as stated in the original question, measure (profile) and optimize your usage based on data. The original statement of “belief” is immaterial — measure… and don’t assume your conclusion in one environment is reasonable for all others from that point on.

If source code consistency is what you’re after, check out any number of coding recommendations from various organizations and choose one to your liking — just be prepared to discover that many coding “standards” are largely orthogonal with other standards… in short, this is a question for the Ministry of Silly Exercises :-/

kai26873
  • 54
  • 2
  • Lots of nice information in there, but the part that's actually relevant to the question `i != length - 1` is actually wrong. -1 – Ben Voigt Jan 17 '12 at 00:29
  • Yeah, I agree this is wrong and so is misleading. I can't downvote, but you should edit the answer. – weston Jan 17 '12 at 09:33