• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Q on post increment: JLS explanation

 
blacksmith
Posts: 979
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi there,
The following expression confused me:

at the end of this i = 6.
I was expecting it to be 7, because there was still
a postfix increment to be performed on the i from line 3.
Furthermore the following code snippet

at the end of this i = 2. So the postfix increment
on line 2 has been performed: as I thought it would.
The behaviour of postfix increment in combination
with array indexes differs.
I hope I haven't overlooked on something, so if
this difference in behaviour is a fact can someone
please tell me where the JLS mentions it, so I can
back it up with some formal lingo.
Thank you, greetings,
Gian Franco Casula
 
Ranch Hand
Posts: 3271
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Let's go through this line by line:

We start evaluating Line 3 with i equal to 1. Therefore, we evaluate operands left to right. The first operand to be evaluated is i. Once we evaluate that operand, we have this:

Next, we must evaluate the post-fixed i used as an array index. Because it's a postfix operator, we use the original value of i, 1, to index the array and then add 1 to i. That gives us this:

Finally, we index the array and get this:

Therefore, when all is said and done, i = 6.
In your other example, we have this:

Once again, we begin by evaluating operands from left to right. First, we evaluate the post-fixed x and get this:

Next we evaluate the pre-fixed x and get this:

Therefore, x = 2.
As you can see, there is no difference in how the post-fix operator works. The key is to remember that operands are evaluated from left to right.
I hope that helps,
Corey
 
Gian Franco
blacksmith
Posts: 979
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Wow that's a quick reply,
I just visited the SCJD asking whether
Marlene Miller could pop by to talk some
JLS: I remember her being a fervent
user of this reference book.
Thank you very much Corey for this
explanation.
Best regards,
Gian Franco
 
Ranch Hand
Posts: 1392
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Gian. As we can see, there is no one who can match Corey for crystal clear explanations.
If you are still interested in JLS formality, I'll give it a try.
========
Let's start with i++ (where i == 1).
JLS 15.15.1 Postfix Increment Operator
1 is added to the value of the variable (1 + 1)
and the sum is stored into the variable (i = 2).
The value of the expression (i++) is the value of the variable (i)
**before** the new value (2) is stored.
----
I prefer to think about i++ this way.
Load (read) the value of the variable i. 1
The value of the expression i++ is 1.
Add 1 to the value of i (1 + 1) and store into the variable i. (i = 2)
========
i = i + a[i++]
The order of evaluation respects implicit operator precedence. (15.7.3)
i = (i + a[i++])
(1) The left-hand operand is evaluated to produce a variable i. (15.26.1)
(2) Then the right-hand operand is evaluated. (15.26.1)
Evaluate: (i + a[i++])
Fully evaluate the left operand i before evaluating the right operand a[i++]. (15.7.1)
The value of the expression i is 1.
Evaluate: a[i++]
Load the value of the variable i. 1
The value of the expression i++ is 1.
Add 1 to the value of i (1 + 1) and store into the variable i.
The variable i holds 2.
Therefore, the value of the expression a[i++] is a[1], or 5,
and the variable i holds 2.
Fully evaluate the operands (i, a[i++]) before performing the operation (+) (15.7.2)
1 + 5
6
(3) Then the value of the right-hand operand is stored into the variable. (15.26.1)
i = 6
[ March 13, 2004: Message edited by: Marlene Miller ]
 
Gian Franco
blacksmith
Posts: 979
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Marlene,
Thank you very much for you explanation!!
Corey's explanation is very good, I wanted
also JLS references though, because I'm trying
to use it more and more as a backup of what
I'm studying.
Thanks again to both of you,
Oh yes...

Originally posted by Marlene Miller:
How did they know where I am? I am quiet as mouse here. Mysterious.
Hi Gian. I'll be right over. I'm not able to help anyone here.


This needed a little investigation and a pinch of luck
Best regards,
Gian Franco
 
Author
Posts: 201
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Corey, technically the postfix should be evaluated first not because it evaluates from left to right but the fact postfix notation has a higher precedence than prefix.
[ March 13, 2004: Message edited by: James Chegwidden ]
[ March 13, 2004: Message edited by: James Chegwidden ]
 
Marlene Miller
Ranch Hand
Posts: 1392
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I think Corey is correct.
Precedence is the stickiness of operators relative to each other. It tells us where to put parentheses.
The left-hand operand of a binary operator appears to be fully evaluated before any part of the right-hand operand is evaluated. JLS 15.7.1
Example 1. ++x is evaluated before x++

Example 2. + is performed before *
 
Marlene Miller
Ranch Hand
Posts: 1392
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

This needed a little investigation and a pinch of luck


 
Marlene Miller
Ranch Hand
Posts: 1392
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Gian Franco,
It think it is ***safe*** to think of postfix increment i++ this way,
load (read) the value of i
The value of the expression i++ is that value.
Then add one to the variable i.
Because the byte codes compute that way.
 
James Chegwidden
Author
Posts: 201
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Ok, with the () around the increment decrement he is correct but if there were no () such as ++x + x++ then the postfix is evaluated first:
JLS 15.7.3- "...Java Programming language implementation must respect the order of evaluation as indicated by parenthesis and implicitly by operator precedence."
[ March 14, 2004: Message edited by: James Chegwidden ]
 
Marlene Miller
Ranch Hand
Posts: 1392
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Even without parentheses, the left operand ++x is evaluated first.

�Operator precedence is the stickiness of operators relative to each other� (TJPL 6.10). Precedence tells us where to add parentheses.
[ March 14, 2004: Message edited by: Marlene Miller ]
 
James Chegwidden
Author
Posts: 201
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Marlene, I think I having problems with "semantics" and definitions here.
I see were you are getting the answer

Take for example: from K & M (partial code):


1. I must be thinking in C- since in ANSI C- the above code is undefined.

2. My problem here is with precedence- JLS 15.7.3 vs. "operands are evaluated from left to right before the operators are applied." JLS 15.7.1
3. In the problem I see to evaluate with respect to precedence.
1. postfix ++ // i = ++k + 1 + +k // k = 2
2. prefix ++ // i = 3 + 1 + + k // k = 3
3. unary + // i = 3 + 1 + 3
4. add results // i = 7
The book says its (2) + (2) + (3) = 7;
4.If I do something simple like:
2 + 6 * 7
if I just go from left to right evaluation with out precedence then the answer is obviously wrong. Precedence * before + would 2 + (6 * 7) would make it correct.
5. Also, in Java 2 Study Guide,2nd ed.:

The book states: Postfix has a precedence over prefix operators.
Then it says after the code above: "The postfix ++ has precedence, so the right side will increment x to 11, but return 10. The left side will then increment x from 11 to 12. So the equation actually looks like x = 12 + 10 which is 22. The exam will likely include a few simple precedence questions like this."
This makes sense to me. Your interpretation seems to disagree with this evalution. Remember I am having problems with the evaluation/interpretation not the result.
I have used/taught prefix/postfix with side effects. Used it for many years in C and C++ and now Java.
So show me why I am "misunderstanding" the interpretation of JLS 15.7.1 and 15.7.3. for the above problems. Am I just having a mental block here?
[ March 14, 2004: Message edited by: James Chegwidden ]
 
Marlene Miller
Ranch Hand
Posts: 1392
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi James. I think I can show you my point of view better with a few examples than by responding **at this moment** to your very compelling examples.
The word precedence does seem to mean Perform the operator with the highest precedence first. But then we observe the following.

I want to consider a different example first.

Which operation is performed first, + | *, and why?
*, because * has higher precedence than + // false
No. In the first example + is performed first. In the second example * is performed first.
Observe:

Therefore, it is NOT true that the operator with the highest precedence is performed first.
What then does precedence mean? How do we determine which operator is performed first?
The ***only clue*** I have is this from The Java Programming Language, co-authored by James Gosling. �Operator precedence is the �stickiness� of operators relative to each other.� 6.10
1. * is stickier than + and | means
* is applied to the nearest operands.

2. + is stickier than | means
+ is applied to the nearest operands.

3. Since the left-hand operand is evaluated before the right-hand operand,
( f(4) + f(5) ) is evaluated before ( f(2) * f(3) )
Therefore, + is performed before *.
----
In the next example, I change + to *. Using +, the result is the same no matter which operand is evaluated first.
k = 2;

postfix ++ is stickier than prefix ++ and *

prefix ++ is stickier than *

Since the left-hand operand is evaluated before the right-hand operand,
(++ k) is evaluated before (k ++)
Now that I understand this, I read JLS 15.7.3, and I see that explicit parentheses and implicit operator precedence are mentioned together, in the section title and in the first sentence.
My best guess is JLS 15.7.3 means precedence determines implicit parentheses.
Marlene
[ March 14, 2004: Message edited by: Marlene Miller ]
 
Gian Franco
blacksmith
Posts: 979
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I'm silently following this discussion, thanks
Marlene these explanations are what I hoped for.
Greetings,
Gian Franco
 
Ranch Hand
Posts: 90
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Marlene, but does it state anywhere which operator is "stickier"?
 
Marlene Miller
Ranch Hand
Posts: 1392
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thank you Gian Franco. I am happy to know this "extension" to your original question applies.
I was worried about going off on a tangent. Some call it hijacking a thread. Very inconsiderate.
And thank you to James for digging deeper and having the courage to confront things that are different from what we are all use to.
[ March 15, 2004: Message edited by: Marlene Miller ]
 
Marlene Miller
Ranch Hand
Posts: 1392
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Marlene, but does it state anywhere which operator is "stickier"?


Hi Bojan.
(1)
The JLS specifies the precedence of operators. The specification occurs in bits and pieces from 15.14 to 15.27. The precedence is presented in the formal language of a context-free grammar (BNF).
Each section 15.14 to 15.17 specifies the operators for a lower level of precedence, except 15.22 ( & ^ | ) which includes 3 levels.
(2)
The Java Programming Language by Arnold, Gosling & Holmes has a table that lists all the operators in order of precedence (section 6.10).
However, there are a few items in that list which do not agree with the JLS:
postfix operators_____ [] . (params) expr++ expr�
unary operators______ ++expr �expr +expr �expr ~ !
creation or cast______ new (type)expr
According to the JLS, [] and . are separators, not operators. (params) is part of a method invocation expression. new is a keyword and is part of a class instance creation expression. cast has the same precedence as the unary operators.
(These deviations from the JLS look like C/C++.)
[ March 15, 2004: Message edited by: Marlene Miller ]
 
reply
    Bookmark Topic Watch Topic
  • New Topic