Why doesn't changing the pre to the post increment at the iteration part of a for loop make a difference?
Asked Answered
S

27

50

Why does this

 int x = 2;
    for (int y =2; y>0;y--){
        System.out.println(x + " "+ y + " ");
        x++;
    }

prints the same as this?

 int x = 2;
        for (int y =2; y>0;--y){
            System.out.println(x + " "+ y + " ");
            x++;
        }

As far, as I understand a post-increment is first used "as it is" then incremented. Are pre-increment is first added and then used. Why this doesn't apply to the body of a for loop?

Sisson answered 16/12, 2009 at 22:17 Comment(2)
for(initialisation; condition; incrementing): yes.Trow
Use javap to produce bytecode for both and see. Be an experimentalist.Montiel
Q
72

The loop is equivalent to:

int x = 2;
{
   int y = 2;
   while (y > 0)
   {
      System.out.println(x + " "+ y + " ");
      x++;
      y--; // or --y;
   }
}

As you can see from reading that code, it doesn't matter whether you use the post or pre decrement operator in the third section of the for loop.

More generally, any for loop of the form:

for (ForInit ; Expression ; ForUpdate)
    forLoopBody();

is exactly equivalent to the while loop:

{
    ForInit;
    while (Expression) {
        forLoopBody();
        ForUpdate;
    }
}

The for loop is more compact, and thus easier to parse for such a common idiom.

Quickman answered 16/12, 2009 at 22:20 Comment(0)
G
35

To visualize these things, expand the for loop to a while loop:

for (int i = 0; i < 5; ++i) {
    do_stuff(i);
}

Expands to:

int i = 0;
while (i < 5) {
    do_stuff(i);
    ++i;
}

Whether you do post-increment or pre-increment on the loop counter doesn't matter, because the result of the increment expression (either the value before or after the increment) isn't used within the same statement.

Ganda answered 18/8, 2010 at 10:19 Comment(0)
K
19

There's no difference in terms of performance, if that's your concern. It can only be used wrongly (and thus sensitive to errors) when you use it during the increment.

Consider:

for (int i = 0; i < 3;)
   System.out.print(++i + ".."); //prints 1..2..3


for (int i = 0; i < 3;)
   System.out.print(i++ + ".."); //prints 0..1..2

or

for (int i = 0; i++ < 3;)
   System.out.print(i + ".."); //prints 1..2..3


for (int i = 0; ++i < 3;)
   System.out.print(i + ".."); //prints 1..2

Interesting detail is however that the normal idiom is to use i++ in the increment expression of the for statement and that the Java compiler will compile it as if ++i is used.

Kiesha answered 12/4, 2010 at 16:45 Comment(3)
However, how he used them there isn't a difference, because the ++i or i++ operation is done alone.Tragedy
The post-increment operator will need to keep the old value available to be used after the incrementation. So your second example needs to hold 0, increment i, remember 0 for the String concatenation.Demonstrative
+1. Never before I thought about for-loop as about 3 lines of usual code.Diplomatics
S
14

++i and i++ makes a difference when used in combination with the assignment operator such as int num = i++ and int num = ++i or other expressions. In above FOR loop, there is only incrementing condition since it is not used in combination with any other expression, it does not make any difference. In this case it will only mean i = i + 1.

Subassembly answered 18/8, 2010 at 10:20 Comment(4)
13 upvotes? But it's wrong! Not only when used with assignment operator: always the result of the expression is to be used (e.g. arithmetic comparisons and method parameters too).Vallejo
@fortran: The question asks about difference between using i++ or ++i in FOR loop. So in context of FOR loop, both mean the same. Can you explain a bit more if my answer is wrong in this context?Subassembly
for(int i = 0; i < 10; doSomething(i++)) or for(i = -1; ++i < 10;) really make a difference if used with pre or post increment... So yes, your assertion, even if it's completely in the context of a for loop (and read it again to check that you aren't specifying the context in the first sentence) is wrong.Vallejo
@fortran: have edited my answer, will this be fine now in the current question context?Subassembly
L
6

This loop is the same as this while loop:

int i = 0;
while(i < 5)
{
     // LOOP
     i++; // Or ++i
}

So yes, it has to be the same.

Loaning answered 18/8, 2010 at 10:18 Comment(1)
@Progman: Wouldn't while(i++ < 5){...} be the equivalent of while(i < 5){i += 1;...} rather than the for-equivalent while(i < 5){...;i += 1;}?Exculpate
E
5

Because that statement is just on it's own. The order of the increment doesn't matter there.

Eddings answered 16/12, 2009 at 22:18 Comment(0)
E
4

Those two cases are equivalent because the value of i is compared after the increment statement is done. However, if you did

if (i++ < 3) 

versus

if (++i < 3)

you'd have to worry about the order of things.

And if you did

i = ++i + i++;

then you're just nuts.

Ema answered 12/4, 2010 at 16:47 Comment(0)
M
3

Because nothing in your examples is using the value returned from the pre- or post-increments. Try wrapping a System.out.println() around the ++x and x++ to see the difference.

Mimesis answered 16/12, 2009 at 22:19 Comment(0)
F
3

From the Java Language Specification chapter on for loops:

BasicForStatement:

    for ( ForInit ; Expression ; ForUpdate ) Statement

... if the ForUpdate part is present, the expressions are evaluated in sequence from left to right; their values, if any, are discarded. ... If the ForUpdate part is not present, no action is taken.

(highlight is mine).

Frock answered 16/12, 2009 at 22:21 Comment(0)
J
3

The output is the same because the 'increment' item in the 'for (initial; comparison; increment)' doesn't use the result of the statement, it just relies on the side-effect of the statement, which in this case is incrementing 'i', which is the same in both cases.

Johniejohnna answered 19/8, 2010 at 9:20 Comment(0)
C
2

Because the value of y is calculated in for statement and the value of x is calculated in its own line, but in the System.out.println they are only referenced.

If you decremented inside System.out.println, you would get different result.

System.out.println(y--);
System.out.println(--y);
Cowbind answered 16/12, 2009 at 22:20 Comment(0)
D
2

The check is done before the increment argument is evaluated. The 'increment' operation is done at the end of the loop, even though it's declared at the beginning.

Durarte answered 12/4, 2010 at 16:46 Comment(0)
K
2

Try this example:

int i = 6;
System.out.println(i++);
System.out.println(i);

i = 10;
System.out.println(++i);
System.out.println(i);

You should be able to work out what it does from this.

Knickerbockers answered 18/8, 2010 at 10:26 Comment(0)
B
1

There are a lot of good answers here, but in case this helps:

Think of y-- and --y as expressions with side effects, or a statement followed by an expression. y-- is like this (think of these examples as pseudo-assembly):

decrement y
return y

and --y does this:

store y into t
decrement y
load t
return t

In your loop example, you are throwing away the returned value either way, and relying on the side effect only (the loop check happens AFTER the decrement statement is executed; it does not receive/check the value returned by the decrement).

Boatwright answered 16/12, 2009 at 22:32 Comment(0)
V
1

If the for loop used the result of the expression i++ or ++i for something, then it would be true, but that's not the case, it's there just because its side effect.

That's why you can also put a void method there, not just a numeric expression.

Vallejo answered 18/8, 2010 at 10:27 Comment(0)
D
0

The increment is executed as an independent statement. So

y--;

and

--y;

are equivalent to each other, and both equivalent to

y = y - 1;

Doby answered 16/12, 2009 at 22:22 Comment(0)
N
0

Because this:

int x = 2;
for (int y =2; y>0; y--){
    System.out.println(x + " "+ y + " ");
    x++;
}

Effectively gets translated by the compiler to this:

int x = 2;
int y = 2
while (y > 0){
    System.out.println(x + " "+ y + " ");
    x++;
    y--;
}

As you see, using y-- or --y doesn't result in any difference. It would make a difference if you wrote your loop like this, though:

int x = 2;
for (int y = 3; --y > 0;){
    System.out.println(x + " "+ y + " ");
    x++;
}

This would yield the same result as your two variants of the loop, but changing from --y to y-- here would break your program.

Natatory answered 16/12, 2009 at 22:25 Comment(0)
D
0

It's a matter of taste. They do the same things.

If you look at code of java classes you'll see there for-loops with post-increment.

Diplomatics answered 12/4, 2010 at 16:45 Comment(2)
They do the same thing if you're not using the result of the expression.Agronomics
@mmyers: you're right. But I've never seen the code which do that (of course, it doesn't mean that that code doesn't exist).Diplomatics
G
0

in your case, it's the same, no difference at all.

Glauce answered 12/4, 2010 at 16:46 Comment(0)
P
0

You are right. The difference can be seen in this case:

for(int i = 0; i < 5; )
       {
            System.out.println("i is : " + ++i);           
       }
Pintail answered 18/8, 2010 at 10:18 Comment(0)
S
0

Yes it does it sequentially. Intialisation, then evaluation condition and if true then executing the body and then incrementing.

Prefix and Postfix difference will be noticable only when you do an Assignment operation with the Increment/Decrement.

Sinistrocular answered 18/8, 2010 at 10:20 Comment(0)
R
0

There is no differences because every part of the for "arguments" are separated statements.

And an interesting thing is that the compiler can decide to replace simple post-incrementations by pre-incrementations and this won't change a thing to the code.

Rist answered 18/8, 2010 at 10:22 Comment(2)
I assume that the (smart) compiler will choose neither post nor pre-incrementation, just add 1 to the variable (i += 1, INC bytecode) since the result is not used in the statement.Savanna
To be precise the ByteCode will be iinc and it will replace i++, ++i and i += 1. I just wanted to say that the compiler will extract the ++i, i++ operation from the statement in every case, to change it in the simple iinc placed before or after the original statement.Rist
T
0

They DON'T behave the same. The construct with i++ is slightly slower than the one with ++i because the former involves returning both the old and the new values of i. On the other side, the latter only returns the old value of i.

Then, probably the compiler does a little magic and changes any isolated i++ into a ++i for performance reasons, but in terms of raw algorithm they are not strictly the same.

Travers answered 18/8, 2010 at 11:24 Comment(4)
Are you sure the performance argument is valid in the for loops case? My guess would be that most compilers are intelligent enough to change i++ for ++i.Goldagoldarina
They DO behave the same. They may(?) have different performance characteristics, but their behaviour is the same.Tetrahedron
Pin: As I and many others say in the answer, probably the compiler is able to swap in the prefix increment in place of the postfix one.Travers
the compiler will change it to a simple INC byte code, equivalent to i += 1.Savanna
I
0

There's many similar posts at Stackoverflow:

However, it seems your question is more generic because it's not specific to any language or compiler. Most of the above questions deal with a specific language/compiler.

Here's a rundown:

  • if we are talking about C/C++/Java (probably C# too) and a modern compiler:
    • if i is an integer (const int, int, etc.):
      • then the compiler will basically replace i++ with ++i, because they are semantically identical and so it doesn't change the output. this can be verified by checking the generated code / bytecode (for Java, I use the jclasslib bytecode viewer).
    • else:
  • else:
    • all bets are off, because the compiler cannot guarantee that they are semantically identical, so it does not try to optimize.

So if you have a class in C++ that overrides the postfix and prefix operators (like std::iterator), this optimization is rarely, if ever, done.

In summary:

  • Mean what you say, and say what you mean. For the increment part of for loops, you almost always want the prefix version (i.e., ++i).
  • The compiler switcheroo between ++i and i++ can't always be done, but it'll try to do it for you if it can.
Illegality answered 18/8, 2010 at 12:16 Comment(0)
A
0

in a loop, first initialization, then condition checking, then execution, after that increment/decrement. so pre/post increment/decrement does not affect the program code.

Airboat answered 9/10, 2010 at 9:34 Comment(0)
P
0

About i++ (post-incrementation) vs. ++i (pre-incrementation) @me: "In both cases, the expression gets evaluated, and the result is used to check against the condition. In the pre-increment case, the increment expression increments the variable and returns the resulting value. For post-increment, the increment expression also increments the variable, but it returns the previous value. As a result, pre-increment compares against the incremented value, whereas post-increment compares against the original value; in both cases, the variable has been incremented when the condition is checked." – tdammers

Predispose answered 22/6, 2011 at 1:14 Comment(0)
T
0

There is quite confusion in between post and pre increment operator, this can be easily understand from this excerpt of "Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne"

Increment/decrement operators: i++ is the same as i = i + 1 and has the value i in an expression. Similarly, i-- is the same as i = i - 1. The code ++i and --i are the same except that the expression value is taken after the increment/ decrement, not before.

for example

x = 0; 
post increment:
x++;
step 1: 
assign the old value (0) value of the x back to x.So, here is x = 0.
step 2:
after assigning the old value of the x, increase the value of x by 1. So,
x = 1 now;

when try to print somthing like:
System.out.print(x++);
the result is x : 0. Because only step one is executed which is assigning 
old value of the x back and then print it.

But when, we do operation like this: 
i++;
System.out.print(i);
the result is x: 1. which is because of executing Step one at first 
statement and then step two at the second statement before printing  the 
value.

pre increment:
++x;
step 1: 
increase the value of x by 1. So, x = 1 now;
step 2:
assign the increased value back to x.

when try to print something like:
System.out.print(++1)  
the result is x : 1. Because the value of the x is raised by 1 and then 
printed. So, both steps are performed before print x value. Similarly, 
executing 
++i;
system.out.print(i);
Both steps are executed at statement one. At second statement, just the 
value of "i" is printed.
Transfusion answered 13/4, 2018 at 14:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.