2

According to http://introcs.cs.princeton.edu/java/11precedence/, post-increment operator has higher precedence than addition operator.

So, for the following code:

    int i = 1;
    int j = i + i++;
    System.out.println(j);

I would have thought that the expression assigned to j would have been evaluated as follows (with each line being a "step" in the evaluation) :

   i + i++
   i + (1)   // do post-increment operator; returns 1, and makes i = 2
   (2) + (1)   // do addition operator. need to get the operand i, so do that.
   3

But when I try this program, the value of j is 2.
So I'm confused. In the expression, does it replace all the "i"s in the expression with the current value of i, BEFORE even touching the i++ ?


Edit: the phrase "evaluation order" that people here used, helped me to find the following potentially helpful stackoverflow answer: What are the rules for evaluation order in Java? .


Edit: I made my best guess into an answer below. I still welcome corrections to it.

Community
  • 1
  • 1
silph
  • 316
  • 2
  • 9

4 Answers4

2

According to Java Language Specification, 15.7.1

The left-hand operand of a binary operator appears to be fully evaluated before any part of the right-hand operand is evaluated.

Hence the i on the left side of the addition operator is evaluated before i++ on the right side.

korolar
  • 1,340
  • 1
  • 11
  • 20
  • that's a lot of reading but probably contains exactly the answer to my question, and the answer to the questions i didn't realize were underneath my question. i might mark your answer as checked after reading through that JLS section. – silph Oct 07 '16 at 22:50
0

Post Increment - First uses previous variable value and then increments.
Pre increment - First increments and then uses new variable value.

int i = 1;
int j = i + i++;
System.out.println(j);// 2
System.out.println(i);// 2

Here first i is substituted with previous i value i,e 1 + again old value of i, so j will become 2, and then i is incremented to 2.

Now consider this code

int i = 1;
int j = i++ + ++i;
System.out.println(j);// 4
System.out.println(i);// 3

Here first i is incremented (pre), so i becomes 2 then i is substituted i,e j = 2 + 2, now j value will be 4 and again i is incremented (post) by one so i's current value will be 3.

Ravikumar
  • 891
  • 12
  • 22
0

Do not let yourself being mislead by the "precedence" word. What the tutorial is stating is that the post-increment operator binds stronger than the addition, as regards parsing expression.

If we made explicit the parentheses, the expression in your example would appear (i + (i++)), not ((i + i)++). That's what precedence means: without explicit parentheses, put them implicitly around the post-increment before, then around the addition.

When the components of the expression have been successfully grouped, evaluation rules are considered. In this case, as Korolar pointed out, JLS 15.7.1 is the paragraph to be considered, which (in simple words) dictates left-to-right evaluation of the addition operation.

FstTesla
  • 844
  • 1
  • 7
  • 10
  • if i understand you correctly, "precedence" is about parsing the characters i type, and not evaluation order. but i hear again and again that for 2 + 5 * 8 , professors say "multiplication has a higher precedence than addition, therefore it gets done first". and indeed, in the link i linked to, the common operators that i'm used to geting evaluated first have higher precedence. so .. it's hard to believe that all my profs have been using the word "precedence" wrong? is there a table out there of "evaluation order" for operators? – silph Oct 09 '16 at 05:46
  • That's right, precedence is about parsing, not evaluation order. Anyway the profs are right in "pure maths", where side effects don't exist and therefore the two aspects coincide. – FstTesla Oct 09 '16 at 07:51
  • Consider the expression `a + b * c`. In this case the addition STARTS to be evaluated, but the multiplication ENDS its evaluation before. If `a` had side effects and you calculated `b + c` before it, as you would do in maths, you would violate the semantics of Java expression evaluation. – FstTesla Oct 09 '16 at 07:58
  • so to be clear, subexpressions are done left to right in Java. so does that mean these are the steps done: 1) evaluate a, 2) evaluate b, 3) evaluate c 4) do the operation b * c, 5) do the operation a + (whatever you got in step four) ? – silph Oct 09 '16 at 16:50
  • 1
    The sequence you said is exact. As regards the evaluation order, Java expressions are generally evaluated left-to-right; short-circuited expressions are the main exception to this rule of thumb. – FstTesla Oct 09 '16 at 17:03
  • FstTelsa, I can accept your `a + b * c` example, but I'm still confused about this example: `int i = 1;` `++i + i++;`. i see two operands (the two `i`s), and three operators (preincrement, addition, and postincrement). if I try to do the operands left-to-right, I will evaluate the two `i`s, and be left with nonesense: ++1 and 1++ . so, i still need clarification on the rule about "operands are all evaluated left-to-right, before operators are evaluated". can yo uhelp me? – silph Oct 10 '16 at 18:49
  • Pre-increment = increment the variable and then take its value as the value of the expression itself. Post-increment = take the value of the variable as the value of the expression itself, THEN increment the variable. As you can see, increment expressions only have meaning with variables ("l-values" would be called in C++), not pure values. Therefore in your last example, `++i` and `i++` are both 2, the final value of `i` is 3, and the addition (of course) 4. – FstTesla Oct 10 '16 at 21:07
  • I know how pre-increment and post-increment works, but my question has instead to do with evaluation order. The rule I'm being told is "first the operators are evaluated from left to right, and then the operands are evaluated by precedence and associativity". I gave the example `++i + i++` not to ask about how pre-increment and post-increment works, but because the rule I just stated does not tell me how to evaluate this line of code. – silph Oct 10 '16 at 22:49
  • Ok, I didn't understand. Increment expressions are within those expressions that don't fit in "general rules", but have its own rule. `i++` (and the pre-inc too) cannot be split into two partial evaluations, one for the variable and one for the expression as a whole; instead, you must do it all together with the increment (in the right order). – FstTesla Oct 11 '16 at 06:46
0

Edit: I do not understand the answers others have given completely, but this is my best guess at what is happening. If someone wants to correct this guess, please do so.

My best guess: a + b * c , where a, b, and c are variables, is made into an expression tree, where the operator with lowest precedence is at the top of the tree:

    +
  /   \
 a     *
      / \
     b    c

Now, this tree is evaluated like so: the + operator gets evaluated. To do so, it (recursively) evaluates the left subtree, and its right subtree, then adds these values.

In full, this is what happens:

  - addition operator gets evaluated.
    it says "evaluate my left subtree, then my right subtree,
    then add them together. i return that value"
        - left subtree: is a. evaluate variable a into a value.
          (that is, get the value of variable a.)
        - right subtree: i'm a multiplication operator. to evaluate me,
          evaluate my left subtree, then my right subtree, the nmultiply
          them togeter. i return that value.
                - left subtree: is variable b. evalute that.
                - right subtree: is variable c. evaluate that.

This is why it a finishes its evaluation first, then b, then c, then b * c, then a + (b * c)

In expressions with ++i stuff, the same thing happens. For example, with ++i + i++, the expression tree would look like this:

          +
         / \
    preinc  postinc
       |      |  
       i      i

where (for example) preinc means the preincrement operator (and preincrement operator takes exactly one operand: a variable). the difference here is that when the subtree that has preinc as its root needs to get evaluated, to "evaluate the preinc operator tree" doesn't mean "replace the variable in the operand with the value of the variable" (the way it would for, say, 2 + i ), but instead it means "increment the value in variable i, and then the value of preinc(i) is the new value in the variable i".

in a similar way, the assignment operator = works a little differently than, say, 2 + i.

    int j;
    j = 3;

the expression tree here is

        =
       / \
      j   3

and when a tree with assignment operator as its root needs to get evaluated, this means "the left hand operator must be a variable -- not a value! and then evaluate the right subtree (we expect it to evaluate it to a value), and then put the value in the right subtree in the variable in the left subtree. Now, the value returned by =(j, 3) is the value in the right subtree".

with this guess, I'm able to correctly come up with the answers given for examples in the Java Language Specification on Evaluation Order (link is: https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.7).

that is, if i draw the expression tree, the following two examples are solvable by me:
example:

  int i = 2;
  int j = (i = 3) * i;
  System.out.println(j);

example:

  int b = 9;
  b = b + (b = 3);
  System.out.println(b);
silph
  • 316
  • 2
  • 9