# assigment order and post increment

Colin Cullen
Greenhorn
Posts: 8
I have occasioned several logs regarding code similar to the following:

This program will print the value: 11

line 3 is the one of interest

i - i++;

I know that coding this way is bad form, and I would never code this
way since it 'looks' basically unsafe, but I encountered this question on a mock exam and was suprised to find that the program printed 11 rather than what I expected, which was 12.

I have read a number of explanations regarding the behavior of this statement. I would like to read the official Sun documentation but I can't seem to find where this behavior is documented. If anyone has already researched this behavior then any help in pointing me the to the documentation would be appreciated. Just the facts, please.

[ Jess added UBB [code] tags to perserve whitespace ]
[ December 23, 2004: Message edited by: Jessica Sant ]

Jessica Sant
Sheriff
Posts: 4313
I'm going to move this to the Programmer's Certification Forum (because you got this from a mock exam, and because these PostInc questions are asked pretty often (they're experts over there).

So please post your replies there, thanks!

Mike Gershman
Ranch Hand
Posts: 1272
i = i++; // line 3

1. copy the value of i from memory to the top of the stack (top of stack = 11)
2. add 1 to the value of i in memory (i = 12)
3. pop the top of the stack and copy the value to i in memory (i = 11)

The key points are that post-increment adds 1 to the variable immediately after it is referenced and that the assignment to the left-hand variable occurs after the right-hand expression hads been fully processed
[ December 23, 2004: Message edited by: Mike Gershman ]

Corey McGlone
Ranch Hand
Posts: 3271
Try giving this a read.

Mark Spritzler
ranger
Sheriff
Posts: 17278
6
Good answer Mike. It is important to realize this, it makes some interesting results.

For instance,

i = 3;
y = i++ + ++i;

afterwards you have
i = 5
y = 8

So obviously we know the i=5 after this because i is incremented twice so 3+2 = 5

But why is y=8 and not 7 or 9.

And I hope Dave can back me up on this one, or correct me.

So the pre-increment is done to make x=4, so at that point 4 + 4 = 8, and this gets assigned to y. Then the post increment on x is performed to make x=5.

Mark

Colin Cullen
Greenhorn
Posts: 8

Output: 11

Let's see Mike ...

1. copy the value of i from memory to the top of the stack (top of stack = 11)

MemoryTop of Stack
push i(11) --> 11

2. add 1 to the value of i in memory (i = 12)

MemoryTop of Stack
inc i(12)11

3. pop the top of the stack and copy the value to i in memory (i = 11)

MemoryTop of Stack
pop i(11) <---11 has been assigned to i in memory (why would java do this?!)

The key points are that post-increment adds 1 to the variable immediately after it is referenced and that the assignment to the left-hand variable occurs after the right-hand expression hads been fully processed

It seems to me, if this were the case, that i should be equal to 12 after the right hand side of the equation is evaluated and therefore i on the left hand side of the equation should then be assigned the value of 12.

Of course this is not the case because, when executed, the program produces 11 as its output. It shouldn't really matter how java implements the underlying stack / variable / value manipulation, since we are viewing the program at a more abstract level, the language specification level. I can't understand why it is considered acceptable for java to simply dispose of the final postfix increment, on the right side of the equation, prior to (or after, I can't tell) making the (what seems to be incorrect) assignment to the left side of the equation. This behavior seems unexpected to me.

I didn't try this earlier, but coming from a C / C++ background I wouldn't have expected the output to be 11, so I wrote a little test in VC++.

If similar code were written in C++ (or simply C for that matter) the result would be different (and expected), e.g.:

Output: 12

Sun must have documented this behavior somewhere, my question is where? Is this trivial or foundational?

Maybe I am totally missing some concept here?

David Harkness
Ranch Hand
Posts: 1646
Originally posted by Mark Spritzler:
For instance,[ ... ]
So the pre-increment is done to make x=4, so at that point 4 + 4 = 8, and this gets assigned to y. Then the post increment on x is performed to make x=5.
Given Mike's clarification, the "x++" evalutes to 3 and assigns 4 to x, and the "++x" assigns 5 to x and evaluates to 5. Thus y = 3 + 5 == 8.

As Mike and Corey's blog entry point out, with post-increment the incrementing happens immediately after the original value is copied as the value of the post-increment expression -- not after the entire statement is evaluated.

Colin Cullen
Greenhorn
Posts: 8
...thanks, but I am still searching for an answer to:

After the above statements are executed I would expect i=4 and y=3, and in the above case
they do (basically Mark's example using two different variables).

However, the example I am working with is a little different
since -- and this is important -- i is the variable on both the left and the right hand sides of
the equation:

After the above statements are executed I would expect i=4, however, in this case, the result is i=3.

This is the scenario I would expect:

i is initialized to 3 via the declaration.
i is assigned its own value of 3 prior to the post increment in the i = i++ statement.
i should then be post incremented to equal 4 after the statement has completed execution -- but it
is not incremented.

My question is what happened to the post incrementation of i?

Why do the following sets of statements (Set 1 and Set 2) produce different results?

I generated the bytecode using javap and (this is the first time I have read bytecode, so I am no
expert) it appears that the post decrement is executed using the iinc JVM statement, but the result
is overwritten by the original value of i, never to be seen from again. This is interesting.

Thanks to all responders.

Colin Cullen
Greenhorn
Posts: 8
...Just for throughness, in case somebody makes a search on this topic, here is the bytecode generated by the following java souce. As you can see the post increment has no effect (iinc in the bytecode), which is why the program prints 9 instead of 10 for the value of i.

Generates the following byte code using javap:

OpStack
bipush99 is pushed to the stack
istore_1---9 poped to local_variable_1
iload_199 is pushed from local_variable_1 to the stack
iinc 1,19local_variable_1 is incremented by 1 (9 + 1 = 10)
istore_199 is poped from the stack and stored in local_variable_1
(and in the process overwrites the value 10 which was previously stored there)

the remainder of the byte codes proceeds to print the value currently
stored in local_variable_1 which is the value 9.

No suprises here, the byte code reflects exactly what happens at runtime.
What happened to the post increment contained in the java source? Well, there
it is on byte 4 of the byte code, but the generated byte code simply overwrites this value at byte 7.

Jeroen Wenting
Ranch Hand
Posts: 5093
I didn't try this earlier, but coming from a C / C++ background I wouldn't have expected the output to be 11, so I wrote a little test in VC++.

If similar code were written in C++ (or simply C for that matter) the result would be different (and expected), e.g.:

code:
--------------------------------------------------------------------------------

#include "stdafx.h" int main(int argc, char* argv[]){ int i = 10; i = ++i; i = i++; printf("i = %d\n", i); return 0;}

--------------------------------------------------------------------------------

Output: 12

Sun must have documented this behavior somewhere, my question is where? Is this trivial or foundational?

Maybe I am totally missing some concept here?

In C++ the outcome of i=i++; is undefined. Your version of VC++ yields i++; as the result, another might yield i;
In Java it is defined to yield i; which is preferable.
Remember Java != C++

Barry Gaunt
Ranch Hand
Posts: 7729
The Java Language Specification (�15.5.1) states: "The value of the postfix increment expression is the value of the variable before the new value is stored."

So i = i++, with an initial value of i = 3, means that i is assigned the value of i++, that is 3.

In the case of i = i++ + i++, i is going to get the value of (i++) + (i++) which will be scanned from left to right to evaluate the arguments. With an initial value of 3, we get (3) + (4), with i holding 5 at this point.

Using a technique I have seen in Dan Chisholm's mocks I wrote this snippet:

The output is:

The value of i is actually incremented during evaluation of the operands and the incremented value is used during operand evaluation.

Barry Gaunt
Ranch Hand
Posts: 7729
I would have used eval instead of mung but UBB freaked out.

Mike Gershman
Ranch Hand
Posts: 1272
Jeroen wrote:
In C++ the outcome of i=i++; is undefined. Your version of VC++ yields i++; as the result, another might yield i;
In Java it is defined to yield i; which is preferable.
Remember Java != C++

Actually, according to Stroustrup's The C++ Programming Language,
For example, y=x++ is equivalent to y=(t=x,x+=1,t), where t is a variable of the same type as x.

Note that z=(alpha,beta,gamma) says to evaluate expressions alpha then beta then gamma in strict sequence and assign the result of evaluating expression gamma to z.

So postfix ++ works the same way in C++ as in Java.

Mike Gershman
Ranch Hand
Posts: 1272
I should have added that Visual C++ is a good illustration of why Sun controls the trademark "Java". C++ is well defined. VC++ differs from C++ in ways that I have not seen spelled out.

Colin Cullen
Greenhorn
Posts: 8
...ok, I brushed the dust off of my Stroustrup...

For example, y=x++ is equivalent to y=(t=x,x+=1,t), where t is a variable of the same type as x.

...thanks Mike, this appears to be what the bytecode is doing. the beta portion of the equation is tossed and never used for anything in the case where the statement contains only a single variable, e.g., i = i++;, and, in the case where two variables are used, j = i++;, the result would be similar to the example presented by Barry. Apparently the VC++ implementation produces incorrect results, according to Stroustrup (3rd ed.).

I did refer to the JLS for clarification, but, I was unable to definitively parse its statement regarding what happens in the case of i = i++;,

JLS (�15.14.1)

At run time, if evaluation of the operand expression completes abruptly, then the postfix increment expression completes abruptly for the same reason and no incrementation occurs. Otherwise, the value 1 is added to the value of the variable and the sum is stored back into the variable. Before the addition, binary numeric promotion (�5.6.2) is performed on the value 1 and the value of the variable. If necessary, the sum is narrowed by a narrowing primitive conversion (�5.1.3) to the type of the variable before it is stored. The value of the postfix increment expression is the value of the variable before the new value is stored.

whereas Stroustrup more formal z=(alpha,beta,gama) statement is clear. Stroustrup's definition makes sense for both i = i++; and j = i++;.

I hope my understanding is correct.

Barry, thanks for indirectly pointing me to Dan Chisholm's mocks.

Mike, thanks for research.

Mike Gershman
Ranch Hand
Posts: 1272
The JLS is more specific than that.

15.7.2 Evaluate Operands before Operation
The Java programming language also guarantees that every operand of an operator (except the conditional operators &&, ||, and ? : ) appears to be fully evaluated before any part of the operation itself is performed.

Remember that in Java, = is a binary operator and "i=i++;" is an expression as well as a statement.

[ December 29, 2004: Message edited by: Mike Gershman ]
[ December 29, 2004: Message edited by: Mike Gershman ]

Warren Dew
blacksmith
Ranch Hand
Posts: 1332
2
So in MSVC++, does:

print "10" or "11"? As it happens, I'm porting something very like this to Java right now.

Colin Cullen
Greenhorn
Posts: 8
What I was calling unexpected behavior in the above thread was the fact that the post-increment seems to be ineffective in the case of i = i++;. When dealing with a 2 variable statement, e.g., j = i++; then the post-increment of the variable i does affect the value of i after the assignment has completed. It appears that MSVC++ does not behave as defined in Stroustrup when executing i = i++;. Consider the following programs, the first in MSVC++ 6.0 and the second in Java 1.4.3. Basically the same code but with different results.

Also note that the post increment of i does in fact cause i to be incremented after the assignment statement j = i++; where i is no longer being assigned to itself. In this case the post-increment is effective, whereas, in the case of i = i++;, the post-increment is discarded. Consider the following program:

As noted by Mike:

Actually, according to Stroustrup's The C++ Programming Language,
quote:
--------------------------------------------------------------------------------
For example, y=x++ is equivalent to y=(t=x,x+=1,t), where t is a variable of the same type as x.
--------------------------------------------------------------------------------

Note that z=(alpha,beta,gamma) says to evaluate expressions alpha then beta then gamma in strict sequence and assign the result of evaluating expression gamma to z.

------
for the statement i = i++; you have,

i = (t = i, i += 1, t) with the gamma (t) being assigned to i and overwriting the value of post-incremented i (the beta). Which is what I intrepret the bytecode to be doing.
------
for the statement j = i++; you have,

j = (t = i, i += 1, t) where the post-incremented value of i is not overwritten because i is not on the left-side of the assignment statement
------

This shouldn't present a problem regarding your port as long as you avoid wacky-scadacky statements like i = i++;, which, syntatically appears to be equivalent to i++; -- but isn't.

Consider:
[CODE]
public class MyTest
{
public static void main(String args [])
{
int i = 10;
i++;
System.out.println(i);

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

}
}

Output:
11
10
[CODE]

Now I gotta go beat a dead horse, and shoo a junk yard dog from my porch, so that I can get back to preparing to pass my Sun Certified Java Post Increment Programmer exam SCJPIP 1.4.

Colin Cullen
Greenhorn
Posts: 8
... I mean symantically equivalent (not syntatically).