45

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);
CodesInChaos
  • 106,488
  • 23
  • 218
  • 262
Marius
  • 57,995
  • 32
  • 132
  • 151
  • 58
    No one should ever write code like this. Believe the compiler - it understands Java better than you do. I think it's correct: the first evaluation returns 3 and the second one returns 4. The final value for a is 5. – duffymo Nov 07 '11 at 16:01
  • 9
    @duffymo: that's what I think about every question on the OCJP exam. – Pops Nov 07 '11 at 16:02
  • 57
    Erm, how you would expect it to be 11 or 13 is beyond me; those are prime numbers. If you'd had said `9` I could see your confusion, sort of. – Brian Roach Nov 07 '11 at 16:02
  • 14
    There's an exam that requires you to know this kind of inanity? – Oliver Charlesworth Nov 07 '11 at 16:03
  • 2
    Are you sure of your expected answers 11 or 13 is only possible if one a++ evaluates to 1 – mmmmmm Nov 07 '11 at 16:03
  • 3
    @Brian: If the `++` occurs right at the end, then you could get 11 (i.e. 3*3 +1 +1). – Oliver Charlesworth Nov 07 '11 at 16:03
  • 22
    It's post-increment, so it's `a = 3 (->4) * 4 (->5) // = 3*4 = 12` – Smamatti Nov 07 '11 at 16:04
  • @LordTorgamus you meant, SCJP, right? Oh, wait :( – Sid Nov 07 '11 at 16:04
  • 1
    does this SCJP exams really help, particularly in finding the better job? I don't think so, honestly... or maybe I'm wrong? does anybody know something definite about that? – javagirl Nov 07 '11 at 16:04
  • Actually, we were both wrong, @SidCool. It's apparently officially now OCPJP. – Pops Nov 07 '11 at 16:06
  • @OliCharlesworth hahahah, very funny! did not you know that ++ has the most priority than any other mathemantical operands? – javagirl Nov 07 '11 at 16:06
  • @duffymo - the final value for a is actually 12 (not 5) since it's on the left of the assignment statement. :) – Ted Hopp Nov 07 '11 at 16:07
  • @javagirl it looks nice in the CV. It should help. – Mister Smith Nov 07 '11 at 16:09
  • @LordTorgamus I guess we both were wrong. I miss Java with Sun. But never mind. javagirl It helped me clear Java basics initially and those have stayed with me for years. I don't say it's a must have, but it's a good one to have. – Sid Nov 07 '11 at 16:10
  • 2
    For all those wondering how the OP expected this to be prime: __If__ the rules of Java were different, and the increment operators were both applied after the assignment, then this would evaluate as 3 * 3 = 9, which would become 11 after two increments. Although this is not what actually happens, there is a reasonable mental path there. – Pops Nov 07 '11 at 16:12
  • @javagirl: Precedence is not necessarily the same as evaluation order (take a look at C or C++). – Oliver Charlesworth Nov 07 '11 at 16:35
  • 1
    @LordTorgamus it's impossible, because ++ cannot be related to expression (for example (a*a*helloworld)++ is nonsense), only to the single variable. and it means that result of this expression in anyway cannot be 11 or 13 – javagirl Nov 07 '11 at 16:45
  • @OliCharlesworth better take yourself look at the core java principles. ++ is never related to expression, only to variables – javagirl Nov 07 '11 at 16:47
  • @TedHopp - thanks, I missed that last assignment. – duffymo Nov 07 '11 at 17:25
  • 1
    @duffymo - you say no one should ever write code like this. I would argue that no one should ever implement a language that allows it! :) – Peter Recore Nov 07 '11 at 18:51
  • 2
    Then you've never written any code. No one's invented the perfect language yet. All languages have flaws that are best avoided. This is one of them. – duffymo Nov 07 '11 at 19:04
  • @javagirl: `a++` means "increment `a` **after** something"; in Java that "something" happens to be well-defined, in C/C++ it isn't well-defined. – Oliver Charlesworth Nov 07 '11 at 19:12
  • @OliCharlesworth well this questions has a tag 'java', isn't it – javagirl Nov 07 '11 at 20:59
  • Maybe the title of this question should be "programmer gives strange java in question." – stu Nov 07 '11 at 21:13
  • @javagirl: Yes, but this is incredibly an incredibly specific detail of the standard that no-one would normally need to know, hence why the OP is asking the question! He/she can be forgiven for coming to the wrong conclusion. – Oliver Charlesworth Nov 07 '11 at 21:34
  • 1
    possible duplicate of [What are the rules for evaluation order in Java?](http://stackoverflow.com/questions/6800590/what-are-the-rules-for-evaluation-order-in-java) – CodesInChaos Nov 08 '11 at 11:11
  • strange results for a strange code - everything's OK – user85421 Nov 08 '11 at 17:13
  • For the follow-up code the value would be 17. It is (3 * (3+1)) + ((3+1)+1) – lokoko Feb 03 '13 at 14:59
  • @lokoko it's actually 15, so i'm guessing it evaluates it as a + (a (a->4) * a(a->5)), or, 3 + (3 * 4) – dardo Mar 22 '13 at 16:53

15 Answers15

109

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)

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
  • Is the order of evaluation of the two `a++` specified? Is it always going to be `3 * 4` or can it be `4 * 3`? – Flexo Nov 07 '11 at 16:07
  • 2
    I"m pretty sure it's left to right in this case. You could prove it by replacing the first a++ to (one() + a++) and the second one with (two() + a++). Make one() and two() both return 0, and put a println inside those methods. At runtime you'll see that one() is called before two(). – Mike Nov 07 '11 at 16:21
  • 1
    cool, i'd never guess that a result could be discarded. my thought was that the final ++ would be applied to the result of the multiplication. – Marius Nov 07 '11 at 16:21
  • 6
    @Marius: It's not so much discarded as overwritten. The second ++ *is* applied, and it *does* increment a to 5... and then the value of a is replaced by the now-evaluated result of the assignment. The fact that you're assigning into the same variable you're using doesn't change the behavior of any of the operators involved. – Bobson Nov 07 '11 at 21:25
  • C++ lets you add to `a` BEFORE using the value as well, using `++a`. DOn't know if Java does this as well. – Ben Brocka Nov 07 '11 at 21:28
  • 1
    @Ben: Java, like C++ and C, has both prefix and postfix increment and decrement: http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.15.1 – Samuel Edwin Ward Nov 07 '11 at 21:47
  • 4
    The main difference between Java and C++ is that Java specifies many more sequence points so that code like this is actually definable, unlike C++ where this code can easily evaluate to any number of things. – fluffy Nov 07 '11 at 22:01
31

Your statement:

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

is equivalent to any of those:

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

Use any of those instead.

Rok Kralj
  • 46,826
  • 10
  • 71
  • 80
  • 5
    *Why does it return 12?* – Robert Harvey Nov 07 '11 at 16:03
  • ps.: I meant multiplication where all factors are >=3, such as it is in the code. – Rok Kralj Nov 07 '11 at 16:04
  • 2
    @RokKralj this is a theoretical question for an exam. It's supposed to be extreme and ambiguous. :) – Madara's Ghost Nov 07 '11 at 16:11
  • My brain has optimized the question, I haven't read the first statement :) Mea culpa. – Rok Kralj Nov 07 '11 at 16:17
  • 1
    Rok should have written "a becomes 4" instead of "a=4" and "a becomes 5", "a=3*4". The "a becomes 5" precedes "a=3*4". – Mike Nov 07 '11 at 16:23
  • +1 for the first sentence alone. And -1 for the exam including this question. – Andy Thomas Nov 07 '11 at 16:23
  • I agree. I oversimplified. This is not a source code, but rather a guideline. Naturally, I would have drawn the steps and variables in a table. Thanks for remark, Mike. – Rok Kralj Nov 07 '11 at 16:24
  • +1 for WHY ON EARTH SHOULD A MULTIPLICATION WITH FACTORS != 1 GIVE A PRIME NUMBER AS A RESULT. – Agos Nov 08 '11 at 22:30
  • 1
    @Agos: I guess he thought that first `3 * 3` would be calculated, then assigned to `a`, and then `a` would be incremented twice --> `11`. Or `3 * 4` is calculated, and the result is incremented once --> `13`. Not that it makes much sense, but if you look at some of the other pre-/postfix increment question here, you get a sense of "anything is possible"... – Tim Pietzcker Nov 09 '11 at 14:25
25

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.

thecoop
  • 45,220
  • 19
  • 132
  • 189
9
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.

CodesInChaos
  • 106,488
  • 23
  • 218
  • 262
7

(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 
Kal
  • 24,724
  • 7
  • 65
  • 65
7

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.

Toast
  • 424
  • 2
  • 9
5

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.

zzzzBov
  • 174,988
  • 54
  • 320
  • 367
5

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.

techExplorer
  • 810
  • 7
  • 16
3

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

lukastymo
  • 26,145
  • 14
  • 53
  • 66
3

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!

pablosaraiva
  • 2,343
  • 1
  • 27
  • 38
2

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.

Mister Smith
  • 27,417
  • 21
  • 110
  • 193
1

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.

Tarik
  • 79,711
  • 83
  • 236
  • 349
1

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

Zeke Hansell
  • 665
  • 2
  • 6
  • 11
0

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
Stu Thompson
  • 38,370
  • 19
  • 110
  • 156
Tessmore
  • 1,054
  • 1
  • 9
  • 23
0

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

Ranga
  • 618
  • 1
  • 8
  • 14
  • talking about precedence is this way is highly misleading. – CodesInChaos Nov 08 '11 at 11:22
  • Because prefix and postfix increments are unary operations (as in they take only one operand) they have a higher precedence. They work like negation. The other thing that should be noted is that there are **PARENTHESES** which force the precedence so that it the compiler isn't really making any choice. -- also you can't use the prefix or postfix increment on anything but a variable - (hence ++(1+2) ) is a non-expression and will be flagged as a syntax error. – Zeke Hansell Nov 08 '11 at 21:31