views:

5935

answers:

16

Is there a performance difference between i++ and ++i if the resulting value is not used?

+62  A: 

Executive summary: No.

i++ could potentially be slower than ++i, since the old value of i might need to be saved for later use, but in practice all modern compilers will optimize this away.

We can demonstrate this by looking at the code for this function, both with ++i and i++.

$ cat i++.c
extern void g(int i);
void f()
{
    int i;

    for (i = 0; i < 100; i++)
        g(i);

}

The files are the same, except for ++i and i++:

$ diff i++.c ++i.c
6c6
<     for (i = 0; i < 100; i++)
---
>     for (i = 0; i < 100; ++i)

We'll compile them, and also get the generated assembler:

$ gcc -c i++.c ++i.c
$ gcc -S i++.c ++i.c

And we can see that both the generated object and assembler files are the same.

$ md5 i++.s ++i.s
MD5 (i++.s) = 90f620dda862cd0205cd5db1f2c8c06e
MD5 (++i.s) = 90f620dda862cd0205cd5db1f2c8c06e

$ md5 *.o
MD5 (++i.o) = dd3ef1408d3a9e4287facccec53f7d22
MD5 (i++.o) = dd3ef1408d3a9e4287facccec53f7d22

~~ Mark Harrison ~~

Mark Harrison
I know this question is about C, but I'd be interested to know if browsers can do this optimization for javascript.
TM
Even if the compiler didn't optimize you'd be very unlikely to notice the difference on any modern CPU.
wds
+2  A: 

Thank you for forking the thread and for analysis. I knew that for integral types, however, I'd like to know if it's working all fine if you work in C++ and implement your own iterators.

poulejapon
+8  A: 

Paul, good point. Since ++i and i++ are really calls to the function operator++, the compiler can't optimize away the temporary intermediate variable. So it's definitely true for C++ objects that ++i is more efficient.

Thanks for that clarification!

Mark Harrison
Yes, for C++, but your question was about C.
Arafangion
A: 

My C is a little rusty, so I apologize in advance. Speedwise, I can understand the results. But, I am confused as to how both files came out to the same MD5 hash. Maybe a for loop runs the same, but wouldn't the following 2 lines of code generate different assembly?

myArray[i++] = "hello";

vs

myArray[++i] = "hello";

The first one writes the value to the array, then increments i. The second increments i then writes to the array. I'm no assembly expert, but I just don't see how the same executable would be generated by these 2 different lines of code.

Just my two cents.

Jason Z
in your example the code would be different, because you're using the value. the example where they were the same was only using the ++ for the increment, and not using the value returned by either.
John Gardner
+2  A: 

In C, the compiler can generally optimize them to be the same if the result is unused.

However, in C++ if using other types that provide their own ++ operators, the prefix version is likely to be faster than the postfix version. So, if you don't need the postfix semantics, it is better to use the prefix operator.

Kristopher Johnson
+1  A: 

@Jason Z

The compiler optimization happens before the assembly is finished being generated, it would see that the i variable is not used anywhere else on the same line, so holding its value would be a waste, it probably effectively flips it to i++. But that's just a guess.

I can't wait till one of my lecturers tries to say it's faster and I get to be the guy who corrects a theory with practical evidence. I can almost feel the animosity already ^_^

Tarks
Fix: "the compiler would see that the return value of i++ is not used, so it would flip it to ++i". What you wrote is wrong also because you can't have i together with one of i++, i++ on the same line (statement), that result is undefined.
Blaisorblade
+1  A: 

Taking a leaf from Scott Meyers, More Effective c++ Item 6: Distinguish between prefix and postfix forms of increment and decrement operations.

The prefix version is always preferred over the postfix in regards to objects, especially in regards to iterators.

The reason for this if you look at the call pattern of the operators.

// Prefix
Integer& Integer::operator++()
{
    *this += 1;
    return *this;
}

// Postfix
const Integer Integer::operator++(int)
{
    Integer oldValue = *this;
    ++(*this);
    return oldValue;
}

Looking at this example it is easy to see how the prefix operator will always be more efficient than the postfix. Because of the need for a temporary object in the use of the postfix.

This is why when you see examples using iterators they always use the prefix version.

But as you point out for int's there is effectively no difference because of compiler optimisation that can take place.

JProgrammer
I think his question was directed at C, but for C++ you're absolutely right, and furthermore C people should adopt this as they can use it for C++ as well. I far too often see C programmers use the postfix syntax ;-)
Anders Rune Jensen
+6  A: 

A better answer is that ++i will sometimes be faster but never slower.

Everyone seems to be assuming that 'i' is a regular built-in type such as int. In this case there will be no measurable difference.

However if 'i' is complex type then you may well find a measurable difference. For i++ you must make a copy of your class before incrementing it. Depending on what's involved in a copy it could indeed be slower since with ++it you can just return the final value.

Foo Foo::operator++()
{
  Foo oldFoo = *this; // copy existing value - could be slow
  // yadda yadda, do increment
  return oldFoo;
}

Another difference is that with ++i you have the option of returning a reference instead of a value. Again, depending on what's involved in making a copy of your object this could be slower.

A real-world example of where this can occur would be the use of iterators. Copying an iterator is unlikely to be a bottle-neck in your application, but it's still good practice to get into the habit of using ++i instead of i++ where the outcome is not affected.

Andrew Grant
The question explicitly states C, no reference to C++.
Dan Cristoloveanu
A: 

@Mark Harrison

The C++ compiler is allowed to eliminate stack based temporaries even if doing so changes program behavior. MSDN link for VC 8:

http://msdn.microsoft.com/en-us/library/ms364057(VS.80).aspx

MSN

Mat Noguchi
As I commtented to this in the other thread, NRVO brings the additional useless copies from 2 to 1; the compiler can't replace i++ with ++i when the definition aren't available (and when inlining is done, it doesn't replace i++ with ++i, it just optimizes to code equivalent to inlined ++i).
Blaisorblade
+1  A: 

@Jason Z: My C is a little rusty, so I apologize in advance.

Nothing wrong with your C, but you didn't read the original question in full:-

Is there a performance difference between i++ and ++i if the resulting value is not used?

Note the italics. In your example, the 'result' of i++/++i is used, but in the idiomatic for loop, the 'result' of the pre/postincrement operator isn't used so the compiler can do what it likes.

Roddy
+7  A: 

Here's an additional observation if you're worried about micro optimisation. Decrementing loops can 'possibly' be more efficient than incrementing loops (depending on instruction set architecture e.g. ARM), given:

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

On each loop you you will have one instruction each for:

  1. Adding 1 to i
  2. Compare whether i is less than a 100
  3. A conditional branch if i is less than a 100

Whereas a decrementing loop:

for (i = 100; i != 0; i--)

The loop will have an instruction for each of:

  1. Decrement i, setting the CPU register status flag
  2. A conditional branch depending on CPU register status (Z==0)

Of course this works only when decrementing to zero!

Remembered from the ARM System Developer's Guide.

tonylo
Good one. But doesn't this create fewer cache hits?
AndreasT
There is an old weird trick from code optimization books, combining advantage of zero-test branch with incremented address. Here's example in high level language(probably useless, since many compilers are smart enough to replace it with _less_ efficient but more common loop code):int a[N];for( i = -N; i ; ++i) a[N+i] += 123;
noop
+12  A: 

From Efficiency versus intent by Andrew Koenig :

First, it is far from obvious that ++i is more efficient than i++, at least where integer variables are concerned.

And :

So the question one should be asking is not which of these two operations is faster, it is which of these two operations expresses more accurately what you are trying to accomplish. I submit that if you are not using the value of the expression, there is never a reason to use i++ instead of ++i, because there is never a reason to copy the value of a variable, increment the variable, and then throw the copy away.

So, if the resulting value is not used, I would use ++i. But not because it is more efficient: because it correctly states my intent.

Sébastien RoccaSerra
Let's not forget that other unary operators are prefix as well. I think ++i is the "semantic" way to use a unary operator, while i++ is around in order to fit a specific need (evaluation before addition).
TM
If the resulting value is not used, there's *no difference* in semantics: i.e., there is no basis for prefering one or the other construct.
Eamon Nerbonne
As a reader, I see a difference. So as a writer, I'll show my intent by choosing one over the other. It's just a habit I have, to try to communicate with my programmer friends and teammates through code :)
Sébastien RoccaSerra
+1  A: 

Please don't let the question of "which one is faster" be the deciding factor of which to use. Chances are you're never going to care that much, and besides, programmer reading time is far more expensive than machine time.

Use whichever makes most sense to the human reading the code.

Andy Lester
I believe it is wrong to prefer vague readability improvements to actual efficiency gains and overall clarity of intent.
noop
My term "programmer reading time" is roughly analogous to "clarity of intent"."Actual efficiency gains" are often immeasurable, close enough to zero to call them zero. In the OP's case, unless the code has been profiled to find that the ++i is a bottleneck, the question of which one is faster is a waste of time and programmer thought units.
Andy Lester
Difference in readability between ++i and i++ is only a matter of personal preference, but ++i clearly implies simpler operation than i++, despite result being equivalent for trivial cases and simple data types when optimizing compiler is involved. Therefore ++i is a winner for me, when specific properties of post-increment are not necessary.
noop
You are saying what I am saying. It is more important to show intent and improve readability than to worry about "efficiency."
Andy Lester
+1  A: 

I always prefer pre-increment, however ...

I wanted to point out that even in the case of calling the operator++ function, the compiler will be able to optimize away the temporary if the function gets inlined. Since the operator++ is usually short and often implemented in the header, it is likely to get inlined.

So, for practical purposes, there likely isn't much of a difference between the performance of the two forms. However, I always prefer pre-increment since it seems better to directly express what I"m trying to say, rather than relying on the optimizer to figure it out.

Also, giving the optmizer less to do likely means the compiler runs faster.

Your posting is C++-specific while the question is about C. In any case, your answer is wrong: for custom post-increment operators the compiler will generally *not* be able to produce as efficient code.
Konrad Rudolph
He states "if the function gets inlined", and that makes his reasoning correct.
Blaisorblade
Since C does not provide operator overloading, the pre vs. post question is largely uninteresting. The compiler can optimize away an unused temp using the same logic that is applied to any other unused, primitively computed value. See the selected answer for a sample.
A: 

@Mark Even though the compiler is allowed to optimize away the (stack based) temporary copy of the variable and gcc (in recent versions) is doing so, doesn't mean all compilers will always do so.

I just tested it with the compilers we use in our current project and 3 out of 4 do not optimize it.

Never assume the compiler gets it right, especially if the possibly faster, but never slower code is as easy to read.

If you don't have a really stupid implementation of one of the operators in your code:

Alwas prefer ++i over i++.

Andreas
A: 

I prefer ++i than i++

sam