x = x++ doesn't increment because the ++ is applied after the assignment?

1.8k views Asked by At

From page 280 of OCP Java SE 6 Programmer Practice Exams, question 9:

int x = 3;
x = x++;
// x is still 3

In the explanation we can read that:

The x = x++; line doesn't leave x == 4 because the ++ is applied after the assignment has occurred.

I agree that x is 3, I understand post-incremenation.

I don't agree with the explanation. I would replace "after" with "before".

I thought it works like this:

  1. x is 3.
  2. x++ is executed. I see this post-increment operator as a function:

    int operator++() {
        int temp = getX();
        setX(temp + 1);
        return temp;
    }
    

    So, after x++ execution, x is 4, but the value returned from x++ expression is 3.

  3. Now, the assignment =. Simply write returned 3 to x.

So, in my eyes ++ is applied before the assignment has occurred. Am I wrong?

4

There are 4 answers

2
Radiodef On BEST ANSWER

...the ++ is applied after the assignment has occurred.

Okay, hold on. This is actually confusing and perhaps suggests an incorrect behavior.

You have the expression:

x = ( x++ )

What happens is (JLS 15.26.1):

  1. The expression on the left-hand side of the assignment x is evaluated (to produce a variable).
  2. The expression on the right-hand side of the assignment ( x++ ) is evaluated (to produce a value).
  3. The evaluation of the right-hand side is: x is post-incremented, and the result of the expression is the old value of x.
  4. The variable on the left-hand side, x, is assigned the value produced by the evaluation of the right-hand side, which is the old value of x.

So the post-increment happens before the assignment.

(Therefore, as we know, the value of x after executing the statement x = x++; is the same as the value of x before executing the statement, which is 3.)

So, in my eyes ++ is applied before the assignment has occurred. Am I wrong?

You are right.

Technically, the way it is specified is that x++ is evaluated before its result is stored and during the evaluation of the assignment operator. So x++ can be interpreted as happening either before or during the assignment. Not after, so the book appears to be wrong either way.

Just for the heck of it, we may also look at some bytecode:

/*                          int x = 3;                           */
iconst_3 // push the constant 3 on to the stack         : temp = 3
istore_0 // pop the stack and store in local variable 0 : x = temp
/*                          x = x++;                             */
iload_0  // push local variable 0 on to the stack       : temp = x
iinc 0 1 // increment local variable 0 by 1             : x = x + 1
istore_0 // pop the stack and store in local variable 0 : x = temp

The iinc happens before the istore.

†: The parentheses have no effect on the evaluation, they are just there for clarity.

3
Sebri Zouhaier On

++x is called preincrement while x++ is called postincrement.

int x = 3;
x = ++x;

exemple

int x = 5, y = 5;

System.out.println(++x); // outputs 6
System.out.println(x); // outputs 6

System.out.println(y++); // outputs 5
System.out.println(y); // outputs 6
0
ALittleHelpFromMyFriends On

x++ means "use x and then increment x."

You can also use ++x, which means "increment x and then use x."

More easily, however, you can simply do

x += 1;
0
Mike 'Pomax' Kamermans On

Reaching over to the official spec:

  1. postfix ++ section: https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.14.2
  2. assignment operator section: https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.26.1

In terms of assignment, this is simple assignment, so we hit case 3:

  1. First, the left-hand operand is evaluated to produce a variable -- x
  2. no errors -> the right-hand operand is evaluated -- x++
  3. "the value of the right-hand operand is converted to the type of the left-hand variable, is subjected to value set conversion (ยง5.1.13) to the appropriate standard value set (not an extended-exponent value set), and the result of the conversion is stored into the variable"

So in step 2, the postfix operator should get resolved, and then in step 3, x gets assigned its original value again:

call: x = x++;
interframe: LHS is variable 'x'
interframe: RHS caches return value as 3
interframe: x is incremented to 4
interframe: RHS cached value '3' is returned for assignment
interframe: variable x is assigned value 3
call result: x = 3

So I think you're right in that the book is wrong, and it might be worth contacting the authors or publisher to have a correction published (or added to an errata page, etc)