Unary operator precedence in java

Now, according to this website, Unary post-increment has more precedence than Unary pre-increment. I presume it meant, that x++ is done before ++x.

However, when tried with the following expression, I've faced problems

int var1=10; 
int b= --var1 + ++var1 + var1++;

Now, if var1++ executes first, then according to me,

b = --var1 + ++var1 + 10   

Now, if I think it should do ++var1 before --var1, as it mentions that the Associativity is Right to Left. I suppose, it means do things on right, before the ones on the left

This, However, doesn't give the correct answer. The Correct Answer is 29, while I get 33. Why is it so ?

Jon Skeet
people
quotationmark

I presume it meant, that x++ is done before ++x.

No, it doesn't mean that. I've previously blogged about how I find viewing precedence in terms of execution order is problematic. It may well be valid in a computer-science-strict way, but it ends up confusing people.

I find it much easier to think about it as grouping. Likewise I think it's easiest to think of associativity as like precedence, but for operators of equal precedence. Evaluation order is always left-to-right.

So this:

int b = --var1 + ++var1 + var1++;

is grouped as if it were written:

int b = (--var1) + (++var1) + (var1++);

That's then equivalent to:

int b = ((--var1) + (++var1)) + (var1++);

(Due to binary + having left-to-right associativity.)

That's then effectively:

int tmp1 = --var1;       // tmp1 = 9, var1 = 9
int tmp2 = ++var1;       // tmp2 = 10, var1 = 10
int tmp3 = tmp1 + tmp2;  // tmp3 = 19
int tmp4 = var1++;       // tmp4 = 10, var1 = 11
int tmp5 = tmp3 + tmp4;  // tmp5 = 29

int b = tmp5;            // b = 29

... which confirms what you've observed.

Of course, you should always try to avoid having code as convoluted as this in the first place...

To demonstrate the evaluation order part, consider this expression:

int result = a() + b() * c();

Precedence means that's grouped as:

int result = a() + (b() * c());

That's equivalent to:

// Evaluate LHS of +, which is just a()
int tmp1 = a();

// Evaluate RHS of +, which is b() * c()
// First evaluate LHS of *, which is b()
int tmp2 = b(); 
// Next evaluate RHS of *, which is c()
int tmp3 = c();
// Now we can evaluate *:
int tmp4 = tmp2 * tmp3;

// Now we can evaluate +:
result = tmp1 + tmp4;

As we're executing methods, we can observe that execution order really easily:

public class Test {
    public static void main(String[] args) throws Exception {
        int result = a() + b() * c();
    }

    public static int a() {
        System.out.println("a()");
        return 3;
    }

    public static int b() {
        System.out.println("b()");
        return 4;
    }

    public static int c() {
        System.out.println("c()");
        return 5;
    }
}

That prints:

a()
b()
c()

... which confirms the execution order shown in my expansion.

people

See more on this question at Stackoverflow