Marius
Marius

Reputation: 59009

a = (a++) * (a++) gives strange results in Java

I'm studying for the OCPJP exam, and so I have to understand every little strange detail of Java. This includes the order in which the pre- and post-increment operators apply to variables. The following code is giving me strange results:

int a = 3;

a = (a++) * (a++);

System.out.println(a); // 12

Shouldn't the answer be 11? Or maybe 13? But not 12!

FOLLOW UP:

What is the result of the following code?

int a = 3;

a += (a++) * (a++);

System.out.println(a);

Upvotes: 45

Views: 8963

Answers (15)

Rok Kralj
Rok Kralj

Reputation: 48775

Your statement:

a += (a++) * (a++);

is just a shorthand for

a = a + (a++) * (a++);

and is equivalent to any of those simpler epressions:

a = a*a + 2*a
a = a*(a+2)
a += a*(a+1)

Use any of those instead.

Upvotes: 31

thecoop
thecoop

Reputation: 46168

a++ means 'the value of a, and a is then incremented by 1'. So when you run

(a++) * (a++)

the first a++ is evaluated first, and produces the value 3. a is then incremented by 1. The second a++ is then evaluated. a produces the value of 4, and is then incremented again (but this doesn't matter now)

So this turns into

a = 3 * 4

which equals 12.

Upvotes: 25

techExplorer
techExplorer

Reputation: 908

In case of :

int a = 3;  
a = (a++) * (a++); 

a = 3 * a++; now a is 4 because of post increment
a = 3 * 4; now a is 5 because of second post increment
a = 12; value of 5 is overwritten with 3*4 i.e. 12 

hence we get output as 12.

In case of :

a += (a++) * (a++); 
a = a + (a++) * (a++);
a = 3 + (a++) * (a++); // a is 3
a = 3 + 3 * (a++); //a is 4
a = 3 + 3 * 4; //a is 5
a = 15

Main point to note here is that in this case compiler is solving from left to right and in case of post increment, value before increment is used in calculation and as we move from left to right incremented value is used.

Upvotes: 5

Zeke Hansell
Zeke Hansell

Reputation: 675

Everyone has clearly explained the first expression, and why the value of a is 12.

For the follow on question, the answer is totally obvious to the casual observer:

17

Upvotes: 1

pablosaraiva
pablosaraiva

Reputation: 2343

Here is the java code:

int a = 3;
a = (a++)*(a++);

Here is the bytecode:

  0  iconst_3
  1  istore_1 [a]
  2  iload_1 [a]
  3  iinc 1 1 [a]
  6  iload_1 [a]
  7  iinc 1 1 [a]
 10  imul
 11  istore_1 [a]

Here is what happens:

Pushes 3 into the stack then pops 3 from the stack and stores it at a. Now a = 3 and the stack is empty.

  0  iconst_3
  1  istore_1 a

Now it pushes the value from "a" (3) into the stack, and then increments a(3 -> 4).

  2  iload_1 [a]
  3  iinc 1 1 [a]

So now "a" equals "4" the stack equals {3}.

Then it loads "a" again (4), pushes into the stack and increments "a".

  6  iload_1 [a]
  7  iinc 1 1 [a]

Now "a" equals 5 and the stack equals {4,3}

So it finally pops the fisrt two values from the stack (4 and 3), multiplies and stores it back into the stack (12).

 10  imul

Now "a" equals 5 and the stack equals 12.

Finally is pops 12 from the stack and stores at a.

 11  istore_1 [a]

TADA!

Upvotes: 3

Tarik
Tarik

Reputation: 81831

Example 1

int a = 3;

a = (++a) * (a++);

System.out.println(a); // 16

Example 2

int a = 3;

a = (++a) * (++a);

System.out.println(a); // 20

Just to make sure where to put ++ expression which changes the value based on the location.

Upvotes: 1

CodesInChaos
CodesInChaos

Reputation: 108880

int a = 3;
a += (a++) * (a++);

First build the syntax tree:

+=
  a
  *
    a++
    a++

To evaluate it start with the outer most element and descent recursively. For each element do:

  • Evaluate children from left to right
  • Evaluate the element itself

The += operator is special: It gets expanded to something like left = left + right, but only evaluating the expression left once. Still the left side gets evaluated to a value(and not just a variable) before the right side gets evaluated to a value.

This leads to:

  1. Start evaluating +=
  2. Evaluate left side of assignment to the variable a.
  3. Evaluate the variable a to the value 3 which will be used in the addition.
  4. Start evaluating *
  5. Evaluate the first a++. This returns the current value of a 3 and sets a to 4
  6. Evaluate the second a++. This returns the current value of a 4 and sets a to 5
  7. Calculate the product: 3*4 = 12
  8. Execute +=. The left side had been evaluated to 3 in the third step and the right side is 12. So it assigns 3+12=15 to a.
  9. Final value of a is 15.

One thing to note here is that operator precedence has no direct influence on evaluation order. It only affects the form of the tree, and thus indirectly the order. But among siblings in the tree the evaluation is always left-to right, regardless of operator precedence.

Upvotes: 9

zzzzBov
zzzzBov

Reputation: 179284

There is a general lack of understanding about how operators work. Honestly, every operator is syntactic sugar.

All you have to do is understand what is actually happening behind every operator. Assume the following:

a = b -> Operators.set(a, b) //don't forget this returns b
a + b -> Operators.add(a, b)
a - b -> Operators.subtract(a, b)
a * b -> Operators.multiply(a, b)
a / b -> Operators.divide(a, b)

Compound operators can then be rewritten using these generalizations (please ignore the return types for the sake of simplicity):

Operators.addTo(a, b) { //a += b
  return Operators.set(a, Operators.add(a, b));
}

Operators.preIncrement(a) { //++a
  return Operators.addTo(a, 1);
}

Operators.postIncrement(a) { //a++
  Operators.set(b, a);
  Operators.addTo(a, 1);
  return b;
}

You can rewrite your example:

int a = 3;
a = (a++) * (a++);

as

Operators.set(a, 3)
Operators.set(a, Operators.multiply(Operators.postIncrement(a), Operators.postIncrement(a)));

Which can be split out using multiple variables:

Operators.set(a, 3)
Operators.set(b, Operators.postIncrement(a))
Operators.set(c, Operators.postIncrement(a))
Operators.set(a, Operators.multiply(b, c))

It's certainly more verbose that way, but it immediately becomes apparent that you never want to perform more than two operations on a single line.

Upvotes: 5

Tessmore
Tessmore

Reputation: 1039

If you use a++ the next time you use a it is incremented by one. So your doing

a = 3 * (3 + 1) = 3 * 4 = 12

Upvotes: 0

Ranga
Ranga

Reputation: 656

Pre & post-prefix increments have a higher precedence than the multiplication operator. hence the expression is evaluated as 3*4.

Upvotes: 0

Mister Smith
Mister Smith

Reputation: 28199

It is 12. The expression starts evaluating from left. So it does:

a = (3++) * (4++);

Once the first part (3++) is evaluated, a is 4, so in the next part, it does a = 3*4 = 12. Note that the last post-increment (4++) is executed but has no effect since a is assigned with the value 12 after this.

Upvotes: 2

lukastymo
lukastymo

Reputation: 26809

(a++) means return a and increment, so (a++) * (a++) means 3 * 4

Upvotes: 3

Toast
Toast

Reputation: 424

Each time the you use a++, you're post-incrementing a. That means the first a++ evaluates to 3 and the second evaluates to 4. 3 * 4 = 12.

Upvotes: 7

Kal
Kal

Reputation: 24910

(a++) is a post increment, so value of expression is 3.

(a++) is post increment, so value of expression is now 4.

Expression evaluation is happening from left to right.

3 * 4 = 12 

Upvotes: 7

Bozho
Bozho

Reputation: 597422

After the first a++ a becomes 4. So you have 3 * 4 = 12.

(a becomes 5 after the 2nd a++, but that is discarded, because the assignment a = overrides it)

Upvotes: 109

Related Questions