• Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Order of evaluation when using post-increment operator

 
Mark Justison
Ranch Hand
Posts: 31
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi,

I have a question regarding operator precedence that is related to a question I got wrong on an enthuware test.
Say I have something simple like this:


My understanding is that this would print '2' because i is stored the value of 0 to start, then 1 is added to i and then i (now 1) is incremented before being assigned back to i. But this prints '1', instead.
Does the ++ increment go unused somehow? Where did I go wrong with this?

Thanks!
-Mark
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Mark Justison wrote:Does the ++ increment go unused somehow? Where did I go wrong with this?

Do you know the difference between the post-increment and pre-increment operator in Java?


Hope it helps!
Kind regards,
Roel
 
Mark Justison
Ranch Hand
Posts: 31
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I know that one is added before the expression and one after the expression. What I don't understand is why it still prints out '1'. Unless I missed my guess (i++ + 1) would first increment i by 1 as if that ++ weren't there i.e. (i + 1) so at this point i is 1, but then when does the increment operator happen? i is still 1 when it prints out.
 
Henry Wong
author
Marshal
Pie
Posts: 22089
88
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Mark Justison wrote:I know that one is added before the expression and one after the expression. What I don't understand is why it still prints out '1'. Unless I missed my guess (i++ + 1) would first increment i by 1 as if that ++ weren't there i.e. (i + 1) so at this point i is 1, but then when does the increment operator happen? i is still 1 when it prints out.


Order of evaluation is left to right. You are correct that "++" operator does increase the i variable to one. And that increment is done immediately after the i variable is used in the expression.

However, the "+=" operator happened earlier, at which point the i variable was still zero. So the "+=" operator will add zero (the i variable at the time of evaluation) to one (the result of the RHS expression), and get to a result of one. The result of one will then replace the current value -- which interestingly, was already one from the post increment.

Or in other words, the post increments happened before the assignment, and the assignment used an pre-post-incremented version of the i variable.

Henry
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Mark Justison wrote:What I don't understand is why it still prints out '1'. Unless I missed my guess (i++ + 1) would first increment i by 1 as if that ++ weren't there i.e. (i + 1) so at this point i is 1, but then when does the increment operator happen? i is still 1 when it prints out.

This lineis equivalent toAnd if we assume i = 0, then we getSo i already was 1 (from the post-increment operator) and it's overwritten with 1 (the result from the += operator)

Let's do the same with the pre-increment operator:
This lineis equivalent toAnd if we assume i = 0, then we getSo i already was 1 (from the pre-increment operator) and it's overwritten with 2 (the result from the += operator)

Hope that makes some sense!
Kind regards,
Roel
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
What's the output of this code?
 
kamal khadka
Greenhorn
Posts: 4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Roel De Nijs wrote:What's the output of this code?



1. Create an int variable called x and initialize it with the value of 10.
2. Assign the value of x ( 10 ) to x and increment the value by 1.
3. Print the value of x ( 10)

So the above code should print out 10.

The value of x is increment after it is assigned to x hence ++ after the variable is called post increment.
 
Campbell Ritchie
Sheriff
Posts: 51341
86
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If you look in the Java® Language Specification (=JLS), it says
JLS wrote:The value of the postfix increment expression is the value of the variable before the new value is stored.
You actually have a value for i and a value for i++ and the two values are different. So in your first post in line 2, the value of the expression immediately after the ( is the old value of i, i.e. 0.

You will doubtless be pleased to hear that particular problem causes no end of confusion to many people. What you wrote in your first post is by no means simple code. You can see the new value of i if you change the code a little
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
kamal khadka wrote:1. Create an int variable called x and initialize it with the value of 10.
2. Assign the value of x ( 10 ) to x and increment the value by 1.
3. Print the value of x ( 10)

I have a doubt. According to step2 you assign the value of x (which is 10) to x and then the value is incremented by 1 --> would you not expect the value of x to be 11 (because you incremented it by 1)?
 
kamal khadka
Greenhorn
Posts: 4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Roel De Nijs wrote:
kamal khadka wrote:1. Create an int variable called x and initialize it with the value of 10.
2. Assign the value of x ( 10 ) to x and increment the value by 1.
3. Print the value of x ( 10)

I have a doubt. According to step2 you assign the value of x (which is 10) to x and then the value is incremented by 1 --> would you not expect the value of x to be 11 (because you incremented it by 1)?



x = x++ is read as assign the current value of x ( it is 10 currently) to x and then increase x by 1.

if the statement was x = ++x then we would read the statement as increment x by 1 ( now x is 11 ) and then assign it to x.

In our case since the assignment occurred before increment therefore System.out.println(x) prints 10.
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
kamal khadka wrote:
Roel De Nijs wrote:
kamal khadka wrote:1. Create an int variable called x and initialize it with the value of 10.
2. Assign the value of x ( 10 ) to x and increment the value by 1.
3. Print the value of x ( 10)

I have a doubt. According to step2 you assign the value of x (which is 10) to x and then the value is incremented by 1 --> would you not expect the value of x to be 11 (because you incremented it by 1)?



x = x++ is read as assign the current value of x ( it is 10 currently) to x and then increase x by 1.

So because x is assigned to 10 and then x is increased by 1, x has to be 11. Not?
 
kamal khadka
Greenhorn
Posts: 4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Roel De Nijs wrote:So because x is assigned to 10 and then x is increased by 1, x has to be 11. Not?


x = x++;

Assign the current value of x ( 10 ) to x so our left most x is 10 now and then add 1 to x. When printing the value of x the assigned value is displayed and the increment in not reflected.

 
Henry Wong
author
Marshal
Pie
Posts: 22089
88
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
kamal khadka wrote:
Assign the current value of x ( 10 ) to x so our left most x is 10 now and then add 1 to x. When printing the value of x the assigned value is displayed and the increment in not reflected.


What if the program goes of and do other stuff for an hour. Then comes back and tries to print x. Does the increment get reflected then?

Henry
 
kamal khadka
Greenhorn
Posts: 4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Henry Wong wrote:

What if the program goes of and do other stuff for an hour. Then comes back and tries to print x. Does the increment get reflected then?

Henry


No it doesn't.

x = x++;
System.out.println(x);

The x++ has no effect.
 
Henry Wong
author
Marshal
Pie
Posts: 22089
88
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Likes 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
kamal khadka wrote:x = x++;
System.out.println(x);

The x++ has no effect.

All joking aside. It does have an effect. It is just not visible via the print() statement in the example.

What happens is ... when the right hand side of the (assignment) expression is evaluated, the increment happens right after the x variable value is used. The x variable gets incremented to 11 during the evaluation of the expression. However, after that, the assignment happens, and since the RHS evaluated to 10, it gets assigned to x.

In other words, the variable is incremented (to 11) temporarily, only to be replaced by the expression result (10) almost immediately.

Henry
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
kamal khadka wrote:x = x++;
System.out.println(x);

The x++ has no effect.

Henry's explanation is spot-on! (For those unfamiliar with RHS, it means "right hand side")

And you can easily illustrate that x++ definitely has an effect, by using another variable to assign the value to as in this code snippetOutput: x = 11, y = 10

Hope it helps!
Kind regards,
Roel
 
Henry Wong
author
Marshal
Pie
Posts: 22089
88
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
For those who don't believe that the expression "x = x++;" has any effect. You can also see the effect with threads.



Run this program, and you will see an eleven appear from time to time.

Henry
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Henry Wong wrote:For those who don't believe that the expression "x = x++;" has any effect. You can also see the effect with threads.

Just wanted to add this informative message.

For those preparing for the OCAJP exam you can just execute the code snippet without having to worry about threads. This topic (threads) is definitely not on the exam. For those preparing for the OCPJP exam, this code is not only an example of the effect of the expression "x = x++;", it's also a nice exercise about threads. So you kill two birds with one stone
 
Guillermo Ishi
Ranch Hand
Posts: 789
C++ Linux Python
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It is really disturbing that this prints 0, because the i++ has occurred before the print statement.
 
Paul Anilprem
Enthuware Software Support
Ranch Hand
Posts: 3817
10
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Guillermo Ishi wrote:It is really disturbing that this prints 0, because the i++ has occurred before the print statement.

Actually, it would be disturbing if it did not print 0 It is using the post increment operator, i.e. use the value and then increment. The value at the time of "use the value" step is the original value i. Since the expression on the right hand side is composed entirely of i++, the original value of i becomes the value of the expression. i is then incremented. Finally, the value of the expression is assigned to the left hand side, thus changing i back to the original value.

If it didn't work like this, there was no need for two different operators i.e. pre and post.
 
Guillermo Ishi
Ranch Hand
Posts: 789
C++ Linux Python
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
These two things should be equivalent. Somebody get on it...

and
 
Mike. J. Thompson
Bartender
Posts: 689
17
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
These two things should be equivalent. Somebody get on it...

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

and

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


Those two steps are not equivalent. Complex expressions (on the right hand side) operate as if their intermediate results are stored in a temporary variable, not the ultimate destination variable on the left hand side.

The assignment operator is the last part of the expression to be executed. The entire right hand side of the expression has to be completely evaluated before that assignment happens. This means that the increment has to happen before the assignment, so the value 'returned' by i++ is stored temporarily while the increment happens.

Your original statement is equivalent to

 
Paul Anilprem
Enthuware Software Support
Ranch Hand
Posts: 3817
10
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Guillermo Ishi wrote:These two things should be equivalent. Somebody get on it...

and

Keep wishing
 
Tapas Chand
Ranch Hand
Posts: 583
8
BSD Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Paul Anilprem wrote:use the value and then increment

Now I am getting little confused about what use the value means.
Doesn't printing means the value has been used?

If I am printing i twice, I am expecting i has been used so now it should have been incremented to 1, but it is again printing 0 at the second print statement.
 
Campbell Ritchie
Sheriff
Posts: 51341
86
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Look at Henry's post where he tells you the value of i is incremented and a nanosecond later reassigned to its old value. And look at our FAQ.
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Guillermo Ishi wrote:These two things should be equivalent. Somebody get on it...

and

When hell freezes over!
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Tapas Chand wrote:Now I am getting little confused about what use the value means.
Doesn't printing means the value has been used?

If I am printing i twice, I am expecting i has been used so now it should have been incremented to 1, but it is again printing 0 at the second print statement.

That's complete nonsense! Why would a value increment if you print it twice? And if you would print it a 3rd time, would it again be incremented by 1?

You could look at Henry's post (which explains very well what's happening) and this post illustrates Henry's explanation using a 2nd variable.

And here is another attempt to illustrate what's going on. In this codethe statement i = i++; is equivalent toAnd that's why i is 0 (and thus 0 is printed each time).
 
Tapas Chand
Ranch Hand
Posts: 583
8
BSD Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Roel De Nijs wrote:And that's why i is 0 (and thus 0 is printed each time).

Yes now it is clear to me, thank you for the explanation
 
Campbell Ritchie
Sheriff
Posts: 51341
86
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Henry: have another question about that threaded version of the code: Have split it here.
 
Mark Justison
Ranch Hand
Posts: 31
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Just realizing that the expression (i++ + 1) is stored separately from the post-fix increment of i really made it clear for me. Thanks for the lengthy and concise explanation!
 
Campbell Ritchie
Sheriff
Posts: 51341
86
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Also the expression i++ has a different value and is stored differently from i.
 
Guillermo Ishi
Ranch Hand
Posts: 789
C++ Linux Python
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Tapas Chand wrote:
Yes now it is clear to me, thank you for the explanation

It is as if i=i++ is a special case where there is shadowing, whatever. The ++ is never available and it's as if it never happened. On the other hand, ii=i++ both would be available.
BTW, in C language i=i++ prints 1 rather than 0.
 
Campbell Ritchie
Sheriff
Posts: 51341
86
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
No, there is nothing special about i = i++; at all. And there is no shadowing. The effect of i++ definitely happens, but it is overwritten by the assignment which has lower precedence and therefore is carried out later. That has already been explained accurately earlier in this discussion.

In C the result of
int i = 3;
i = i++;
printf("%d\n", i);

is not strictly defined. I tried that sort of thing once and got 3 from two compilers and 4 from a third! It is strictly defined in Java® so such code in Java® would always produce the result 3.
 
Jesper de Jong
Java Cowboy
Saloon Keeper
Posts: 15627
46
Android IntelliJ IDE Java Scala Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Guillermo Ishi wrote:BTW, in C language i=i++ prints 1 rather than 0.

Not always. This is typically one of those things that in C is left undefined by the language standard. Maybe your C compiler will make this print 1, but someone else's C compiler will make it print 0. Or even on your C compiler with different options (for example a different optimization level setting) the result might suddenly be different.

In Java, fortunately not many things are left undefined like in C, so that in Java the result is predictable, if you just follow the rules.
 
Mike. J. Thompson
Bartender
Posts: 689
17
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I think this thread shows why it is a bad idea to use the increment operators in compound expressions since it makes it harder to reason about the code. There's no point shortening code by a few characters if the meaning is obfuscated.
 
Guillermo Ishi
Ranch Hand
Posts: 789
C++ Linux Python
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Jesper de Jong wrote:In Java, fortunately not many things are left undefined like in C, so that in Java the result is predictable, if you just follow the rules.

I don't think ISO/IEC 9899:2011 would let something so flagrant get by. Unfortunately it costs money to read it
Campbell Ritchie wrote:No, there is nothing special about i = i++; at all. And there is no shadowing. The effect of i++ definitely happens, but it is overwritten by the assignment which has lower precedence and therefore is carried out later. That has already been explained accurately earlier in this discussion..

I read that, thank you. I was talking about the effect, not some analogy for the internals. The effect of i++ most definitely does not happen. And it is only seen when the left and right side are the same variable, so yes the effect is a special case..
 
Joe Bishara
Ranch Hand
Posts: 175
17
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Mike. J. Thompson wrote:I think this thread shows why it is a bad idea to use the increment operators in compound expressions since it makes it harder to reason about the code. There's no point shortening code by a few characters if the meaning is obfuscated.

I agree. I can't see a practical need for doing an assignment inside an assignment - as in i += (i++ + 1) - except when an exam wants to test in-depth knowledge of the ++ operator.
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Guillermo Ishi wrote:I was talking about the effect, not some analogy for the internals. The effect of i++ most definitely does not happen. And it is only seen when the left and right side are the same variable, so yes the effect is a special case..

The effect of i++ does indeed definitely happenAnd the effect of the assignment does happen as well
 
Guillermo Ishi
Ranch Hand
Posts: 789
C++ Linux Python
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Roel De Nijs wrote:
The effect of i++ does indeed definitely happen

We are having an English problem, not a Java problem. What I said or attempted to say was the effect of i++ is not seen when the variable on the left and right are the same. I don't deny that i may be incremented somewhere in i=i++, but the effect of that isn't seen. Your j = i++ isn't that special case of when the effect of i++ isn't seen...
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic