8

I've had to do a Java exam recently, and was wondering about one of the questions I had wrong. The question was as follows:

What will the following code print when run without any arguments ...

public class TestClass {

    public static int m1(int i){
        return ++i;
    }

    public static void main(String[] args) {
        int k = m1(args.length);
        k += 3 + ++k;
        System.out.println(k);
    }

}

With the answers being a number between 1 and 10. My original answer was 7, whereas they state that the correct one is 6.

My logic:

m1 sets k to 1, as it's ++i and thus gets incremented prior to returning.
then the += is unrolled, making: 'k = k + 3 + ++k'.
++k is executed, making k 2.
Replace the variables with their value: 'k = 2 + 3 + 2'
k = 7.

However, they state it as k = 1 + 3 + 2. Could anyone explain as to why the variable is replaced first, before performing the ++k?

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
  • You should simply read this [documentation about operator priority](https://docs.oracle.com/javase/tutorial/java/nutsandbolts/operators.html). You will find the order for `postfix`, `additive` and `assignment` – AxelH Nov 28 '16 at 11:06
  • @AxelH That page states that ++ has precedence over +=, meaning that my answer would actually be correct? – Joey van Gangelen Nov 28 '16 at 11:10
  • This is more complicate, like you can see ^^ but I have done some research (more like try and see) and we can find some logic that seems to hold. PS : I would have failed because in C, args contains the name of the program in the list ... so I would have done the math with `args.length = 1` :( – AxelH Nov 28 '16 at 12:15
  • See also http://stackoverflow.com/questions/6800590/what-are-the-rules-for-evaluation-order-in-java and http://stackoverflow.com/questions/18991306/java-pre-postfix-operator-precedences – Tunaki Nov 28 '16 at 14:09
  • @Tunaki, I don't agree with the duplicate you used, in the other hand, the [seconds link](http://stackoverflow.com/questions/18991306/java-pre-postfix-operator-precedences) of your comment is clearly the duplicate. This was not about the pre/post increment but about the priority with assignment operator. This is completly missed in the "duplicate question". Just saying ;) – AxelH Nov 29 '16 at 08:59
  • @AxelH Yeah I found it later, and it has more explanations given, so it is better. I think I'll start using this one for new questions, we need a very good canonical for those type of questions. – Tunaki Nov 29 '16 at 09:07
  • @Tunaki, I agree, might be an idea for a documentation, I didn't checked there. – AxelH Nov 29 '16 at 09:13

4 Answers4

3

The post and pre increment operators do operate on a temporary value which is getting assigned after the equation. Which means that

i = 0;
i = i++ // still 0
i = ++i // 1

Because the right hand side is temporary and do not reflect the left side before the assignment.

With your logic this would result in

int i = 0;
i = ++i // 2 - wrong.
Murat Karagöz
  • 35,401
  • 16
  • 78
  • 107
2

Without any arguments means args.length = 0

int k = m1(args.length); m1 (0) = ++0 = 1

So k = 1

k += 3 + ++k;

k = k + 3 =4. ++k = ++1 = 2

So

4 + 2 = 6

M.Sarmini
  • 70
  • 3
  • Meaning that the ++k is performed when it reaches that part of the equation, not prior to the entire equation itself? – Joey van Gangelen Nov 28 '16 at 10:48
  • according to this [Java Operator Precedence Table](http://www.cs.bilkent.edu.tr/~guvenir/courses/CS101/op_precedence.html) the ++ operator has higher precedence than the += operator suggesting the OP is correct in assuming that the += is unrolled **after** the ++ is evaluated. – David Nov 28 '16 at 11:02
2

I do believe that even if the order is correct, the JVM prepare the statement with the k value so this is looking like this (simplified) :

  k += 3+ ++k; // k = 1
> k = k + 3 + ++k // k = 1
> k = 1 + 3 + ++k // k = 1 
> k = 1 + 3 + 2   // k = 2

Let go further with :

  int k = 2;
  k *= 3 + ++k; // > 12
> k = 2 * 3 + ++k // k = 2
> k = 2 * 3 + ++k // k = 2
> k = 2 * 3 + 3   // k = 3
> k = 2 * 6 = 12

We see that the *= is done last be with the beginning value.

  int k = 1;
  k += 3 + ++k + ++k; // > 9
> k = k + 3 + ++k + ++k // k = 1
> k = 1 + 3 + ++k + ++k // k = 1
> k = 1 + 3 + 2   + ++k // k = 2
> k = 1 + 3 + 2   + 3   // k = 3
> k = 9

So we can see that this is not true for post increment. Those will get the value of k on the first reading

The only logic I see is that the values are evaluated from left to right but the operator are only executed depending on the order. At the exception of post and pre increment that are evaluated during the first reading

AxelH
  • 14,325
  • 2
  • 25
  • 55
  • It seems to be that any variable that has no ++ or -- attached to it is replaced prior to performing any operators (or at least, based on the answers given above), which is the same as your reply. However, you mention postfix while your example shows a prefix, do postfixes work way differently than prefixes? (Other than being executed before or after replacing the variable with the value) – Joey van Gangelen Nov 28 '16 at 12:43
  • @JoeyvanGangelen Indeed, I mixed my words ... Well, you resumed this with your first sentences. Only `++` and `--` are evaluated during the replacement of values. The other operators are executed afeter – AxelH Nov 28 '16 at 12:53
  • @JoeyvanGangelen I just found that [question](http://stackoverflow.com/questions/13369393/a-a-a-a-in-java-how-does-it-get-evaluated) that is quiete similar. You mind find some info their – AxelH Nov 28 '16 at 13:09
  • Thanks for the link :) Unfortunately, that question is considerably easier to resolve due to it being the same operand throughout. Fortunately though, the question is clear to me by now :D – Joey van Gangelen Nov 29 '16 at 08:48
  • @JoeyvanGangelen There are some comments that helps. Plus the complexity is the same, you only works with `k`, one operand. using `args.length` doesn't change a thing. – AxelH Nov 29 '16 at 08:53
  • I went over them and they do indeed provide some additional clarity. The complexity I was talking about though is that that link uses k++ * k++ * k++ which is the same mathematical operator as well as the same location of the ++ – Joey van Gangelen Nov 29 '16 at 11:46
1

Ok, you are correct in stating that the ++ operator has precedence over the += operator and therefore the += will not be unrolled until the ++ operation has been carried out .... however before any operation is carried out the interpreter first evaluates the operands of most operators and this is done from left to right.

So in your example, where k = 1,

k += 3 + ++k;

effectively is:

1 += 3 + ++k;

and then the ++k is evaluated as this has precedence and becomes:

1 += 3 + 2;

the + has precedence and becomes:

1 += 5;

and at this point the += is unrolled, which of course gives 6 ... QED

Edit

Although operator precedence is important Java does evaluate left to right unless the precedence dictates otherwise:

For example:

a + b + c * d

Although c * d has precedence it isn't evaluated first.

a + b + c * d
  ^   ^
 these 2 operators compared

Both have same level of precedence so evaluating left to right and a + b is evaluated first (lets call the result d).

 d + c * d
   ^   ^
 next these 2 operators compared

* has precedence over + so c * d is evaluated first.

David
  • 3,510
  • 3
  • 21
  • 39
  • Thank you :) This would mean that the order in which k and ++k (k = k + 3 + ++k) has no relevance? – Joey van Gangelen Nov 28 '16 at 11:37
  • correct.... you can try testing out expressions online [Javascript Console](https://jsconsole.com) – David Nov 28 '16 at 11:41
  • I end up with this same conclusion except that I only see the postfix that are evaluated directly, every other operator just take the current value of the variable, from left to right. (See some example I have put in my answer) PS : A Javascript console to run Java, is it really safe ? Don't know if Javascript use the same rules. – AxelH Nov 28 '16 at 11:51
  • reading further into it ... my solution does seem too simplistic – David Nov 28 '16 at 11:53
  • Well, I have done a lot of test, some are in my answer (with a lot of edit ^^). The only logic I see is that the first reading (the evaluation of the statement) will replace the variable with there value AND run the postfix (because of their priority). Meaning that the variable on the left of a postfix won't have the udpate but those on the right will. – AxelH Nov 28 '16 at 12:13
  • @AxelH ah not so.... `k += ++k + k` gives same result as `k =+ k + ++k` – David Nov 28 '16 at 12:17
  • You mean `k += k + ++k` > 4 and `k += ++k + k` > 5. At least, on Java 1.6 – AxelH Nov 28 '16 at 12:24
  • @AxelH hmmm interesting ... i was evaluation using https://jsconsole.com/ ... it's Javascript but you would assume that the rules for interpreting operands, operators, and associatives would be the same as for Java - evidently not. – David Nov 28 '16 at 12:35
  • 1
    @David you assume that one language have the same logic off an other, they only have part of their names identical ;) nothing more. That's what I warn you about. Use [Ideone](http://www.ideone.com) – AxelH Nov 28 '16 at 12:36
  • @AxelH ah ty .. already tested on https://www.compilejava.net ... and you are indeed correct. I believe now that evaluation is carried out left to right **unless** precedence of the next operator takes priority. – David Nov 28 '16 at 12:46