views:

4218

answers:

16

Is there a difference in ++i and i++ in a for loop? Is it simply a syntax thing?

+7  A: 

One (++i) is preincrement, one (i++) is postincrement. The difference is in what value is immediately returned from the expression.

// Psuedocode
int i = 0;
print i++; // Prints 0
print i; // Prints 1
int j = 0;
print ++j; // Prints 1
print j; // Prints 1

Edit: Woops, entirely ignored the loop side of things. There's no actual difference in for loops when it's the 'step' portion (for(...; ...; )), but it can come into play in other cases.

Cody Brocious
How does this answer the question about loops?
Adam Peck
Also, the second (++i) should be (i++)
Brett Daniel
Thanks Adam, helps to actually answer the question asked :P
Cody Brocious
Thanks Brett, just saw your comment -- caught it about the same time you did haha.
Cody Brocious
+26  A: 

In c# there is no difference when used in a for loop.

for (int i = 0; i < 10; i++) { Console.WriteLine(i); }

outputs the same thing as

for (int i = 0; i < 10; ++i) { Console.WriteLine(i); }

As others have pointed out, when used in general i++ and ++i have a subtle yet significant difference:

int i = 0;
Console.WriteLine(i++);   // Prints 0
int j = 0;
Console.WriteLine(++j);   // Prints 1

i++ reads the value of i then increments it.

++i increments the value of i then reads it.

Jon B
Concluding: the same post / pre increment semantics as in C++.
xtofl
@xtofl - not sure what your point is? I just happened to pick c# for my example.
Jon B
I don't think that the first point is relevant. In a for loop (c# or not) the increment part is always executed after the body of the loop. Once executed, the variable is modified whether post or pre increment was used.
MatthieuP
@MatthieuP - I read the question as "does it matter whether you use i++ or ++i in a for loop". The answer is "no it does not".
Jon B
@Jon B - Just a sidenote. Making links, that's all.
xtofl
@Jon B: Oops! Sorry, my mistake !
MatthieuP
+3  A: 

Yes, there is. The difference is in the return value. The return value of "++i" will be the value after incrementing i. The return of "i++" will be the value before incrementing. This means that code that looks like the following:

int a = 0;
int b = ++a; // a is incremented and the result after incrementing is saved to b.
int c = a++; // a is incremented again and the result before incremening is saved to c.

Therefore, a would be 2, and b and c would each be 1.

I could rewrite the code like this:

int a = 0; 

// ++a;
a = a + 1; // incrementing first.
b = a; // setting second. 

// a++;
c = a; // setting first. 
a = a + 1; // incrementing second.
David Morton
I think you meant to write int c = a++; (not b++, right?)
David Kolar
Yes. Thanks. :)
David Morton
A: 

There is no actual difference in both cases 'i' will be incremented by 1.

But there is a difference when you use it in an expression, for example:

int i = 1;
int a = ++i;
// i is incremented by one and then assigned to a.
// Both i and a are now 2.
int b = i++;
// i is assigned to b and then incremented by one.
// b is now 2, and i is now 3
CMS
+47  A: 

Pre-increment ++i increments the value of i and evaluates to the new incremented value.

int i = 3;
int preIncrementResult = ++i;
Assert( preIncrementResult == 4 );
Assert( i == 4 );

Post-increment i++ increments the value of i and evaluates to the original non-incremented value.

int i = 3;
int postIncrementResult = i++;
Assert( postIncrementtResult == 3 );
Assert( i == 4 );


In C++, the pre-increment is usually prefered where you can use either.

This is because if you use post-increment, it can require the compiler to have to generate code that creates an extra temporary variable. This is because both the previous and new values of the variable being incremented need to be held somewhere because they may be needed elsewhere in the expression being evaluated.

So, in C++ at least, there can be a performance difference which guides your choice of which to use.

This is mainly only a problem when the variable being incremented is a user defined type with an overridden ++ operator. For primitive types (int, etc) there's no performance difference. But, it's worth sticking to the pre-increment operator as a guideline unless the post-increment operator is definitely what's required.

There's some more discussion here:
http://en.allexperts.com/q/C-1040/Increment-operators.htm

In C++ if you're using STL, then you may be using for loops with iterators. These mainly have overridden ++ operators, so sticking to pre-increment is a good idea. Compilers get smarter all the time though, and newer ones may be able to perform optimizations that mean there's no performance difference - especially if the type being incremented is defined inline in header file (as STL implementations often are) so that the compiler can see how the method is implemented and can then know what optimizations are safe to perform. Even so, it's probably still worth sticking to pre-increment because loops get executed lots of times and this means a small performance penalty could soon get amplified.


In other languages such as C# where the ++ operator can't be overloaded there is no performance difference. Used in a loop to advance the loop variable, the pre and post increment operators are equivalent.

Scott Langham
Wouldn't it have been great if C++ was named ++C indicating that you can write a well optimized code using it..
Naveen
Shouldn't modern compilers be able to optimize this when the resulting value is obviously going to be trashed anyway?
che
@che, yes, there should be no difference in generated code for primitive types
Jay Conrod
@che - they do when it's a simple type, however classes that overload operator++ (such as iterators) are a different story.
Ferruccio
@Scott: re: "For primitive types (int, etc) there's not much performance difference" It's safe to say that there's NO performance difference.
Shmoopty
@che: That's a good question. The reason that C++ compilers don't replace "CustomType++;" with "++CustomType;" is because there's no guarantee that both user-defined functions have the same effect. They SHOULD...but there's no guarantee.
Shmoopty
+10  A: 

Since you ask about the difference in a loop, i guess you mean

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

In that case, you have no difference in most languages: The loop behaves the same regardless of whether you write i++ and ++i. In C++, you can write your own versions of the ++ operators, and you can define separate meanings for them, if the i is of a user defined type (your own class, for example).

The reason why it doesn't matter above is because you don't use the value of i++. Another thing is when you do

for(int i=0, a = 0; i<10; a = i++) 
    ...;

Now, there is a difference, because as others point out, i++ means increment, but evaluate to the previous value, but ++i means increment, but evaluate to i (thus it would evaluate to the new value). In the above case, a is assigned the previous value of i, while i is incremented.

Johannes Schaub - litb
In C++, it is not always possible for the compiler to avoid making the temporary, so the pre-increment form is preferred.
David Thornley
as i write, if you have an i of user defined type, they could have different semantics. but if you use an i of primitive type, then it does not make a difference for the first loop. as this is a language agnostic question, i figured not to write too much about C++ specific stuff.
Johannes Schaub - litb
A: 

As @Jon B says, there is no difference in a for loop.

But in a while or do...while loop, you could find some differences if you are making a comparison with the ++i or i++

while(i++ < 10) { ... } //compare then increment

while(++i < 10) { ... } //increment then compare
crashmstr
two downvotes? What is wrong with what I wrote? And it is related to the question (as vague as it is).
crashmstr
A: 

For i's of user-defined types, these operators could (but should not) have meaningfully different sematics in the context of a loop index, and this could (but should not) affect the behavior of the loop described.

Also, in c++ it is generally safest to use the pre-increment form (++i) because it is more easily optimized. (Scott Langham beat me to this tidbit. Curse you, Scott)

dmckee
The semantics of postfix are _supposed_ to be bigger than prefix. -1
xtofl
+10  A: 

a++ is known as postfix.

add 1 to a, returns the old value.

++a is known as prefix.

add 1 to a, returns the new value.

C#:

string[] items = {"a","b","c","d"};
int i = 0;
foreach (string item in items)
{
    Console.WriteLine(++i);
}
Console.WriteLine("");

i = 0;
foreach (string item in items)
{
    Console.WriteLine(i++);
}

Output:

1
2
3
4

0
1
2
3

So it depends how you use it.

Chris S
Am I the only one who is perplexed as to why this is the accepted answer?
Jon B
No Jon. I'm just as perplexed on how it go so many upvotes.
grom
Apparently, not only did many of the answers miss the point of the question, so did the guy who *wrote* the question.
Graeme Perrow
+9  A: 

As this code shows (see the dissambled MSIL in the comments), the C# 3 compiler makes no distinction between i++ and ++i in a for loop. If the value of i++ or ++i were being taken, there would definitely be a difference (this was compiled in Visutal Studio 2008 / Release Build):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PreOrPostIncrement
{
    class Program
    {
        static int SomethingToIncrement;

        static void Main(string[] args)
        {
            PreIncrement(1000);
            PostIncrement(1000);
            Console.WriteLine("SomethingToIncrement={0}", SomethingToIncrement);
        }

        static void PreIncrement(int count)
        {
            /*
            .method private hidebysig static void  PreIncrement(int32 count) cil managed
            {
              // Code size       25 (0x19)
              .maxstack  2
              .locals init ([0] int32 i)
              IL_0000:  ldc.i4.0
              IL_0001:  stloc.0
              IL_0002:  br.s       IL_0014
              IL_0004:  ldsfld     int32 PreOrPostIncrement.Program::SomethingToIncrement
              IL_0009:  ldc.i4.1
              IL_000a:  add
              IL_000b:  stsfld     int32 PreOrPostIncrement.Program::SomethingToIncrement
              IL_0010:  ldloc.0
              IL_0011:  ldc.i4.1
              IL_0012:  add
              IL_0013:  stloc.0
              IL_0014:  ldloc.0
              IL_0015:  ldarg.0
              IL_0016:  blt.s      IL_0004
              IL_0018:  ret
            } // end of method Program::PreIncrement             
             */
            for (int i = 0; i < count; ++i)
            {
                ++SomethingToIncrement;
            }
        }

        static void PostIncrement(int count)
        {
            /*
                .method private hidebysig static void  PostIncrement(int32 count) cil managed
                {
                  // Code size       25 (0x19)
                  .maxstack  2
                  .locals init ([0] int32 i)
                  IL_0000:  ldc.i4.0
                  IL_0001:  stloc.0
                  IL_0002:  br.s       IL_0014
                  IL_0004:  ldsfld     int32 PreOrPostIncrement.Program::SomethingToIncrement
                  IL_0009:  ldc.i4.1
                  IL_000a:  add
                  IL_000b:  stsfld     int32 PreOrPostIncrement.Program::SomethingToIncrement
                  IL_0010:  ldloc.0
                  IL_0011:  ldc.i4.1
                  IL_0012:  add
                  IL_0013:  stloc.0
                  IL_0014:  ldloc.0
                  IL_0015:  ldarg.0
                  IL_0016:  blt.s      IL_0004
                  IL_0018:  ret
                } // end of method Program::PostIncrement
             */
            for (int i = 0; i < count; i++)
            {
                SomethingToIncrement++;
            }
        }
    }
}
Joe Erickson
A: 

There can be a difference for loops. This is the practical application of post/pre-increment.

        int i = 0;
        while(i++ <= 10) {
            Console.Write(i);
        }
        Console.Write(System.Environment.NewLine);

        i = 0;
        while(++i <= 10) {
            Console.Write(i);
        }
        Console.ReadLine();

While the first one counts to 11 and loops 11 times, the second does not.

Mostly this is rather used in a simple while(x-- > 0 ) ; - - Loop to iterate for example all elements of an array (exempting foreach-constructs here).

Leonidas
+1  A: 

Is there a performance difference between i++ and ++i in C? From StackOverFlow

ecleel
+1  A: 

There is more to ++i and i++ than loops and performance differences. ++i returns a l-value and i++ returns an r-value. Based on this, there are many things you can do to ( ++i ) but not to ( i++ ).

1- It is illegal to take the address of post increment result. Compiler won't even allow you.
2- Only constant references to post increment can exist, i.e., of the form const T&.
3- You cannot apply another post increment or decrement to the result of i++, i.e., there is no such thing as I++++. This would be parsed as ( i ++ ) ++ which is illegal.
4- When overloading pre-/post-increment and decrement operators, programmers are encouraged to define post- increment/decrement operators like:

T& operator ++ ( )
{
   // logical increment
   return *this;
}

const T operator ++ ( int )
{
    T temp( *this );
    ++*this;
    return temp;
}
Tanveer Badar
A: 

In javascript due to the following i++ may be better to use:

var i=1;
alert(i++); // before, 1. current, 1. after, 2.
alert(i); // before, 2. current, 2. after, 2.
alert(++i); // before, 2. current, 3 after, 3.

While arrays (I think all) and some other functions and calls use 0 as a starting point you would have to set i to -1 to make the loop work with the array when using ++i.

When using i++ the following value will use the increased value. You could say i++ is the way humans count, cause you can start with a 0.

xaddict
A: 

Thanks guys!

A great round of answers by everyone and all the different implications covered.

My main language is C# so I am interested in the way the CLR interprets the two approaches (which a poster has talked about).

Thanks again.

dotnetdev
+3  A: 

Here is a Java-Sample and the Byte-Code, post- and preIncrement show no difference in Bytecode:

public class PreOrPostIncrement {

static int somethingToIncrement = 0;

public static void main(String[] args) {
    final int rounds = 1000;
    postIncrement(rounds);
    preIncrement(rounds);
}

private static void postIncrement(final int rounds) {
    for (int i = 0; i < rounds; i++) {
        somethingToIncrement++;
    }
}

private static void preIncrement(final int rounds) {
    for (int i = 0; i < rounds; ++i) {
        ++somethingToIncrement;
    }
}

}

And now for the byte-code (javap -private -c PreOrPostIncrement):

public class PreOrPostIncrement extends java.lang.Object{
static int somethingToIncrement;

static {};
Code:
0:  iconst_0
1:  putstatic #10; //Field somethingToIncrement:I
4:  return

public PreOrPostIncrement();
Code:
0:  aload_0
1:  invokespecial #15; //Method java/lang/Object."<init>":()V
4:  return

public static void main(java.lang.String[]);
Code:
0:  sipush 1000
3:  istore_1
4:  sipush 1000
7:  invokestatic #21; //Method postIncrement:(I)V
10: sipush 1000
13: invokestatic #25; //Method preIncrement:(I)V
16: return

private static void postIncrement(int);
Code:
0:  iconst_0
1:  istore_1
2:  goto 16
5:  getstatic #10; //Field somethingToIncrement:I
8:  iconst_1
9:  iadd
10: putstatic #10; //Field somethingToIncrement:I
13: iinc 1, 1
16: iload_1
17: iload_0
18: if_icmplt 5
21: return

private static void preIncrement(int);
Code:
0:  iconst_0
1:  istore_1
2:  goto 16
5:  getstatic #10; //Field somethingToIncrement:I
8:  iconst_1
9:  iadd
10: putstatic #10; //Field somethingToIncrement:I
13: iinc 1, 1
16: iload_1
17: iload_0
18: if_icmplt 5
21: return

}
Mirko Friedenhagen