Win a copy of The Little Book of Impediments (e-book only) this week in the Agile and Other Processes forum!

# Priority of Post and Pre Unary Operators

avi neo
Greenhorn
Posts: 6
This is regarding the following code example provided in the section Increment and Decrement Operators of the book OCA Java 8 Study Guide by Boyarsky and Selikof :

From the subsequent explanation it looks like the processing is done from left to right in the following sequence:

• x is increased by pre-increment operator (++x)
• Then it is decreased by post-decrement operator (x--)
• Finally it is decreased by pre-decrement operator (--x)

• As mentioned in the book, post-unary operators have higher precedence than pre-unary operators.

Shouldn't the sequence have been something as follows ?
• x is decreased by post-decrement operator (x--)
• Then it is increased by pre-increment operator (++x)
• Finally it is decreased by pre-decrement operator (--x)

• It would be great if somebody can clarify my doubt.

Daniel Cox
Ranch Hand
Posts: 147
7
avi neo wrote:As mentioned in the book, post-unary operators have higher precedence than pre-unary operators.

Shouldn't the sequence have been something as follows ?
• x is decreased by post-decrement operator (x--)
• Then it is increased by pre-increment operator (++x)
• Finally it is decreased by pre-decrement operator (--x)

• The fact that an operator has a higher precedence than another operator:
• has no effect on the order of evaluation of operands (the order of evaluation of operands is always left to right)
• has an effect on the order of evaluation of operators (operators with a higher precedence are always evaluated first)

• Things are a little different with postfix and prefix operators. I asked a question here about these operators and my conclusion is that the fact that postfix increment/decrement operators have a higher precedence than prefix increment/decrement operators:
• has no effect on the order of evaluation of operands (the order of evaluation of operands is always left to right)
• has no effect on the order of evaluation of operators

• The interesting thing about postfix and prefix operators is that they do have an impact on the evaluation of operands; however, they do not have an impact on the order of evaluation of operands.

Stephan van Hulst
Bartender
Posts: 6503
83
• 8
This is misleading David. Operators are not evaluated, because they are not expressions. Operations are evaluated.

Order of evaluation is always from left to right, no matter if the expression is a literal, a variable or an operation, even an operation with a prefix or postfix operator.

The ONLY thing that operator precedence does is determine which operands go with which operators. You can picture operator precedence as if the compiler implicitly inserts extra parentheses in your code:

After that's done, the expression is evaluated left to right:

Daniel Cox
Ranch Hand
Posts: 147
7
Stephan van Hulst wrote:Operators are not evaluated, because they are not expressions.

Thanks for the correction

Ganesh Patekar
Bartender
Posts: 696
23
@Stephan Great explanation in detail. I can use this example explanation to solve other examples.

Roel De Nijs
Sheriff
Posts: 10662
144
• 2
Hi avi neo,

First of all, a warm welcome to CodeRanch!

avi neo wrote:It would be great if somebody can clarify my doubt.

That's really a very common question (confusion) on this forum! You should definitely read this topic and this one as both topics provide excellent explanations (with illustrative code snippets) about the same code snippet. And if you want to learn more about the order of evaluation of (post-)increment (& decrement) operators, this topic is also definitely worth reading. And if you want to learn more about evaluating boolean expressions with short-circuit operators this topic and this one are must-read topics.

Hope it helps!
Kind regards,
Roel

Roel De Nijs
Sheriff
Posts: 10662
144
Ganesh Patekar wrote:@Stephan Great explanation in detail.

It is indeed a great explanation Have a cow, Stephan!

Ganesh Patekar
Bartender
Posts: 696
23
Roel De Nijs wrote:
Ganesh Patekar wrote:@Stephan Great explanation in detail.

It is indeed a great explanation Have a cow, Stephan!
My one cow = 2 likes so gave him, at least for a month(Pie user) Thank you for the links of treasure of operator evaluations, seems like It will take at least a day.

Liutauras Vilda
Bartender
Posts: 2792
112
It is indeed a great explanation. Have a cow, Stephan!
+1 great post.

Stephan van Hulst
Bartender
Posts: 6503
83
Thanks guys ^^

Daniel Cox
Ranch Hand
Posts: 147
7
Stephan van Hulst wrote:
After that's done, the expression is evaluated left to right:

There's something I'm not clear about. My understanding is that all of the operands in the expression will first be evaluated from left to right before any operation takes place

so this

++x * 5 / x-- + --x;

becomes this

4 * 5 / 4 + 2;

After evaluation of all of the operands in the expression is complete, operators then operate on their operands based on precedence and associativity. So based on precedence and associativity, operators operate on their operands in this order

(((4 * 5) / 4) + 2);

so this executes first

4 * 5

followed by

20/4

followed by

5 + 2

Henry Wong
author
Marshal
Posts: 22113
88
Daniel Cox wrote:My understanding is that all of the operands in the expression will first be evaluated from left to right before any operation takes place

After evaluation of all of the operands in the expression is complete, operators then operate on their operands based on precedence and associativity. So based on precedence and associativity, operators operate on their operands in this order

No. Evaluation of the whole expression is done left to right. Also, the precedence is applied to everything, including the pre/post operators.... so, apply precedence/assoc to the whole expression, and then evaluate the expression from left to right.

Also note... Just because the evaluation is from left to right, it doesn't mean that the operation will finish left to right. For example (ignoring compile time constant optimization)...

a = 4 + 5 * 2;

The plus operator is evaluated before the multiply operator, but the multiply operator will finish before the plus operator. The reason is, due to precedence, the plus operation can't complete until the right operand (for it) is determined (which is after the multiply operator is applied).

Additionally, this is true for the assignment operator. The assignment operator is evaluated first, as it is the leftmost operator, but can't complete until the rest of the expression value has been determined.

Henry

Stephan van Hulst
Bartender
Posts: 6503
83
Daniel Cox wrote:My understanding is that all of the operands in the expression will first be evaluated from left to right before any operation takes place.

No.

You should consider variable evaluation to be an operation. It is performed after other operations to its left, but before operations to its right. This has important side effects:

This expression will return true, and the final value of x will be 2, not 3. This is because the short-circuiting || operation is performed before the second ++ operation, because it's on the left.

Daniel Cox
Ranch Hand
Posts: 147
7
Thanks Stephan and Henry. It's much clearer now. An expression is evaluated from left to right. Precedence determines which operands bind to which operators.

Daniel Cox
Ranch Hand
Posts: 147
7
Stephan van Hulst wrote:Operators are not evaluated, because they are not expressions. Operations are evaluated.

Just one more thing. Sometimes, information we get on the ranch conflicts with information we get from articles and books, so just to be clear, I want to confirm that these corrections are valid.
• This statement in this princeton article

• Java has well-defined rules for specifying the order in which the operators in an expression are evaluated when the expression has several operators.

should be

Java has well-defined rules for specifying the order in which the operations in an expression are evaluated when the expression has several operators.

• This statement in Just Java 2 (2004) page 77

• In Java, the precision of evaluating an operator depends on the types of its operands. Java looks at the types of the operands around an operator and picks the biggest of what it sees: double, float, and long, in that order of preference.

should be

In Java, the precision of evaluating an operation...

• Henry's statement in this thread

• The plus operator is evaluated before the multiply operator...

should be

The plus operation is evaluated before the multiply operation...

Roel De Nijs
Sheriff
Posts: 10662
144
Daniel Cox wrote:Just one more thing. Sometimes, information we get on the ranch conflicts with information we get from articles and books, so just to be clear, I want to confirm that these corrections are valid.

I think that's a potato-patato thing. Even the Operators section of the Trail: Learning the Java Language tutorial mentions that "operators are evaluated"
Trail: Learning the Java Language - Language Basics - Operators wrote:As we explore the operators of the Java programming language, it may be helpful for you to know ahead of time which operators have the highest precedence. The operators in the following table are listed according to precedence order. The closer to the top of the table an operator appears, the higher its precedence. Operators with higher precedence are evaluated before operators with relatively lower precedence. Operators on the same line have equal precedence. When operators of equal precedence appear in the same expression, a rule must govern which is evaluated first. All binary operators except for the assignment operators are evaluated from left to right; assignment operators are evaluated right to left.

Stephan van Hulst
Bartender
Posts: 6503
83
It's called a pars pro toto. It's similar to people referring to The United Kingdom as Britain.

It's not technically correct, but it's generally accepted because the intention is clear.

Henry Wong
author
Marshal
Posts: 22113
88
Stephan van Hulst wrote:
It's not technically correct, but it's generally accepted because the intention is clear.

In this context, I would argue that the word "operation" is also incorrect. In fact, I would say that it is more incorrect.

We are discussing the order of evaluation in this topic, specifically, how the evaluation is done left to right. And by "done", I mean how the parser is moving left to right. The word "operation" implies the actual task... in order words, the "plus operation" is implies the task of taking the sum. The actual task of doing the operation, ie. the sum, can't happen until the right operand has been calculated, which is after all higher precedence "operations" needed to calculate the right operand completes first.

Anyway... Po"tay"to -- Po"ta"to. The intention is clear regardless.

Henry

avi neo
Greenhorn
Posts: 6
Thank you everyone for responding to the query.

Special thanks to Stephan for the step-by-step explanation.

Also thanks to Roel, Daniel and Henry for providing lot of information.

Daniel Cox
Ranch Hand
Posts: 147
7
• 2
I thought I'd summarize my understanding of this evaluation

In this expression

int x = 3;
int y = ++x * 5 / x-- + --x;

the order in which operators will bind to their operands is dictated by operator precedence as follows:

(((++x) * 5) / (x--)) + (--x)

At runtime, the JVM evaluates this expression as follows.

EVALUATION 1 (STARTS)
The + operator’s operation on its operands (((++x) * 5) / (x--)) and (--x) is evaluated first

(((++x) * 5) / (x--)) + (--x)

EVALUATION 2 (STARTS)
The / operator’s operation on its operands ((++x) * 5) and (x--) is evaluated next

(((++x) * 5) / (x--)) + (--x)

This evaluation is done during the evaluation of the + operator’s left operand ((++x) * 5) / (x--)

EVALUATION 3 (STARTS)
The * operator’s operation on its operands (++x) and 5 is evaluated next

(((++x) * 5) / (x--)) + (--x)

This evaluation is done during the evaluation of the / operator’s left operand ((++x) * 5)

EVALUATION 4 (STARTS  AND ENDS)
Evaluation of the * operator’s left operand (++x) results in a value of 4

(((++x) * 5) / (x--)) + (--x)
(((4) * 5) / (x--)) + (--x)

EVALUATION 3 (ENDS)
Evaluation of the * operator’s operation on its operands 4 and 5 results in a value of 20

(((4) * 5) / (x--)) + (--x)
((20) / (x--)) + (--x)

EVALUATION 5 (STARTS  AND ENDS)
Evaluation of the / operator’s right operand (x--) results in a value of 4 (with a side effect of setting x to 3)

((20) / (x--)) + (--x)
((20) / (4)) + (--x)

EVALUATION 2 (ENDS)
Evaluation of the / operator’s operation on its operands 20 and 4 results in a value of 5

((20) / (4)) + (--x)
((5)) + (--x)

EVALUATION 6 (STARTS AND ENDS)
Evaluation of the + operator’s right operand (--x) results in a value of 2

5 + (--x)
5 + (2)

EVALUATION 1 (ENDS)
Evaluation of the + operator’s operation on its operands 5 and 2 results in a value of 7

5 + 2
7

Stephan van Hulst
Bartender
Posts: 6503
83
Great job!

Yes, evaluation is performed recursively on sub-expressions. Sub-expressions on the left are evaluated before sub-expressions on the right.

Roel De Nijs
Sheriff
Posts: 10662
144
Stephan van Hulst wrote:Great job!

It is indeed! Have a well-deserved cow, Daniel!

And here is a little pop quiz question. What's the output of this code snippet?

Daniel Cox
Ranch Hand
Posts: 147
7
Roel De Nijs wrote:And here is a little pop quiz question. What's the output of this code snippet?

x++  evaluates to the value of x before the increment
++x  evaluates to the value of x after the increment
So the answer to the question is 0

Liutauras Vilda
Bartender
Posts: 2792
112
And personally myself I found this Roel's given some time ago example very well explaining evaluation order concept.

Roel wrote:

What would be printed?

Daniel Cox
Ranch Hand
Posts: 147
7
Liutauras Vilda wrote:What would be printed?

In this expression

++i + --i * --j

the operators will bind to their operands (based on operator precedence) as follows:

(++i) + ((--i) * (--j))

At runtime, the JVM evaluates this expression as follows

EVALUATION 1 (STARTS)
The + operator’s operation on its operands (++i) and ((--i) * (--j)) is evaluated first

(++i) + ((--i) * (--j))

EVALUATION 2 (STARTS AND ENDS)
The + operator’s left operand (++i) is evaluated next to a value of 6.

(++i) + ((--i) * (--j))
(6) + ((--i) * (--j))

EVALUATION 3 (STARTS)
The * operator’s operation on its operands (--i) and (--j) is evaluated next

(6) + ((--i) * (--j))

This evaluation occurs during the evaluation of the + operator’s right operand ((--i) * (--j))

EVALUATION 4 (STARTS AND ENDS)
The * operator’s left operand (--i) is evaluated next to a value of 5.

(6) + ((--i) * (--j))
(6) + ((5) * (--j))

EVALUATION 5 (STARTS AND ENDS)
The * operator’s right operand (--j) is evaluated next to a value of 9.

(6) + ((5) * (--j))
(6) + ((5) * (9))

EVALUATION 3 (ENDS)
Evaluation of the * operator’s operation on its operands 5 and 9 completes and results in a value of 45

(6) + ((5) * (9))
(6) + (45)

EVALUATION 1 (ENDS)
Evaluation of the + operator’s operation on its operands 6 and 45 completes and results in a value of 51

6 + 45
51

Liutauras Vilda
Bartender
Posts: 2792
112
It seems you mastered this topic. Have a cow

Daniel Cox
Ranch Hand
Posts: 147
7
• 1
Liutauras Vilda wrote:It seems you mastered this topic.

I think I have. Thanks to Stephan, Roel and Henry.