Java Forum / General / April 2007
Question about ++
richnjones@gmail.com - 09 Apr 2007 16:36 GMT Hello all,
I have got a question about the post increment operator. Consider the following code
int i = 1; System.out.println(i); i = i++; System.out.println(i);
The output is 1 1
I expect the first 1 because I am (for sanities sake) outputting the value of i before any operations are done on it.
I then expect the value of i on the right of the = to be assigned to the i on the left of the equals. I expect that to copy it and then the increment to happen. I do not see why the increment is not done on teh i to the left of the equals. I know this is with primitives whcih pass by value but I was expected an output of 1 2
It seems int he code above the ++ is completly disregarded
What made me think of this is another question in the forum
(http://groups.google.co.uk/group/comp.lang.java.programmer/ browse_thread/thread/ fb0d3fbd12040ba3/5153c4175a471b0a#5153c4175a471b0a)
asking the answer to
int a = 1; int b = a++ + a++; System.out.println("A = " + a); System.out.println("B = " + b);
in C. I tried it in Java and the b=.... line seemed to be doing operations left to right although Im not too clear with this either
The output is
A = 3 B = 3
Can anyone clarify what is expected when ++ and assigning
Thanks
Daniel Pitts - 09 Apr 2007 16:54 GMT On Apr 9, 8:36 am, richnjo...@gmail.com wrote:
> Hello all, > [quoted text clipped - 47 lines] > > Thanks try this simple example: class Increments { public static void main(String[] args) { int a = 0; int b = 0; System.out.println(a++); System.out.println(a); System.out.println(++b); System.out.println(b); } }
The output would be: 0 1 1 1 ... a++ is called the "Post increment operator", meaning that after the current statement completes, a will be incremented. "++a" is the "pre increment operator" meaning that a will be incremented, and its new value used.
In either case, you should never use "x = x++", just use "x++" or "+ +x".
x = x++ is similar to "int _tmp = x; x = x + 1; x = _tmp" Yuck.
Patricia Shanahan - 09 Apr 2007 18:47 GMT ...
> a++ is called the "Post increment operator", meaning that after the > current statement completes, a will be incremented. "++a" is the "pre > increment operator" meaning that a will be incremented, and its new The "after the current statement" model works for some cases, but fails to explain why
public class YuckyTest { public static void main(String[] args) { int a = 1; int b = a++ + a++; System.out.println(b); } }
prints 3, not 2.
In the JLS they are called "postfix increment operator" and "prefix increment operator", making the "post" or "pre" refer to the syntax, not the functionality.
Patricia
Luc The Perverse - 09 Apr 2007 22:13 GMT > The "after the current statement" model works for some cases, but fails > to explain why [quoted text clipped - 6 lines] > } > } If I saw that I think I'd have to slap whoever wrote it!
Well . . unless it was a NG example.
-- LTP
:) Patricia Shanahan - 09 Apr 2007 17:06 GMT > Hello all, > [quoted text clipped - 22 lines] > > It seems int he code above the ++ is completly disregarded If you really want to understand code like "i=i++;", you need to understand the definition of postfix ++ in Java, http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.15.1
There are a couple of significant aspects to every operation:
1. What result, if any, does it provide for use in subsequent calculations?
2. What side effects does it have?
For postfix ++, the result is the old value of the variable, and the side effect is to increment the variable by 1.
Java completely evaluates the right hand side of an assignment before performing the assignment. The sequence for i=i++; with i initially 1 is:
Determine the left hand side field - trivial because it is not an array access or anything else that might have side effects.
Evaluate the right hand side Calculate the result, 1 Perform the side effect, change i to 2
Do the assignment, setting i to the right hand side result, 1.
Of course, a smart optimizer might decide all this is a waste of time, and do nothing, but the results will be the same as though this was all done.
> What made me think of this is another question in the forum > [quoted text clipped - 16 lines] > A = 3 > B = 3 Evaluate the right hand side Evaluate the left operand of the binary + Result is old value of a, 1 Side effect, change a to 2 Evaluate the right hand side of the + Result is old value of a, 2 Side effect, change a to 3 Evaluate the binary + Result is sum of the left and right hand side results, 3 Do the assignment, setting b to the right hand side result, 3
> Can anyone clarify what is expected when ++ and assigning My usual expectation when code combines ++ and assigning is very confused, unreadable code that probably does not do what the programmer intended. Even if done "correctly" in the sense of getting the intended result, it is a warning sign of code that sacrifices clarity in favor of unnecessary cleverness.
Patricia
richnjones@gmail.com - 09 Apr 2007 17:36 GMT > richnjo...@gmail.com wrote: > > Hello all, [quoted text clipped - 97 lines] > > - Show quoted text - Thanks for the replies. I would never use code like i=i++; but was curious to see what happened. I'll look at the link you posted Patricia and if I have any other questions I'll come back to you Thanks again
Luc The Perverse - 09 Apr 2007 17:37 GMT > I have got a question about the post increment operator. Consider the > following code *snip*
Daniel and Patricia offered excellent explanations about what is going on.
One thing that is important to note is that the statement
i=i++;
really doesn't make any sense. In Java, it can never change the value of i, no matter the data type of i. It's typically just something that teachers put on tests and assignments to see if people are paying attention or understanding the underlying concepts.
If you were trying to increment i then just use
i++
If you wanted to increment i and save a copy of the old value, it would be more clear to write.
int oldI = i; i++;
But you ~could~ compress those into one line like this
int oldI = i++;
Though I can't really think of a practical reason that you would want to do that
-- LTP
:) Lew - 10 Apr 2007 14:54 GMT > int oldI = i++; > > Though I can't really think of a practical reason that you would want to do > that Lookahead algorithms. Sometimes it's convenient to know both i and i+1 without having to repeat the addition all the time.
In any case an idiom like this would be part of a very local block.
 Signature Lew
Patricia Shanahan - 10 Apr 2007 15:51 GMT >> int oldI = i++; >> [quoted text clipped - 5 lines] > > In any case an idiom like this would be part of a very local block. But why not code it as
int oldI = i; i++;
which completely avoids multiple side effects in one statement?
Patricia
Luc The Perverse - 10 Apr 2007 17:53 GMT > But why not code it as > > int oldI = i; > i++; > > which completely avoids multiple side effects in one statement? What!
Have you never heard of "obfuscation" ?
-- LTP
:) Tor Iver Wilhelmsen - 13 Apr 2007 19:40 GMT På Mon, 09 Apr 2007 18:37:31 +0200, skrev Luc The Perverse <sll_noSpamlicious_z_XXX_m@cc.usu.edu>:
> i=i++; > > really doesn't make any sense. Well, it can be useful in C/C++ which don't define the consequence of that statement. :)
int main(int argc, char** argv) { int i = 1; i = i++; if (i != 1) { printf("I disagre with what the compiler has done with me and will terminate.\n"); printf("Plese recompile me with a compiler that is not like totally WRONG.\n"); exit(0); } else { /* Do something useful */ } }
angrybaldguy@gmail.com - 14 Apr 2007 06:21 GMT On Apr 13, 11:41 am, "Tor Iver Wilhelmsen" <tori...@operamail.com> wrote:
> Well, it can be useful in C/C++ which don't define the consequence of that > statement. :) ...
> int i = 1; > i = i++; [quoted text clipped - 5 lines] > exit(0); > } You can do that, but it's still wrong. In C++ with primitive types the statement i = i++; is free to leave i == 1 but also format your hard drive, or corrupt some random piece of the stack, or invite your in-laws over to stay with you. More practically, the above code is likely to be VERY sensitive to optimization settings and may well trigger even when the program's logic would otherwise run fine.
In short, Don't Do That.
ruds - 11 Apr 2007 05:34 GMT On Apr 9, 8:36 pm, richnjo...@gmail.com wrote:
> Hello all, > [quoted text clipped - 47 lines] > > Thanks You are using the post increment operator ++,so when u r writing i=i++; the actual value of i is first asigned and then i is incremented. so first assignment takes place and then increment.
Chris Smith - 24 Apr 2007 04:24 GMT > > int i = 1; > > System.out.println(i); [quoted text clipped - 4 lines] > > 1 > > 1
> You are using the post increment operator ++,so when u r writing > i=i++; > the actual value of i is first asigned and then i is incremented. > so first assignment takes place and then increment. That is not true. Obviously, if it were true, then the given output would be different. If the assignment happened first (setting i to 1) and then the increment (setting i to 2), then the second line of output would read "2". It doesn't, so that execution model is wrong. I don't know who it was that first described the behavior of post-increment in terms of when the increment happens. Whoever first spread that misunderstanding about Java should be ashamed of themselves.
What really happens is that the expression is evaluated whenever the evaluator gets to it. Nothing is delayed or put off. The evaluation has a side-effect (incrementing the variable) and a result (the value of the variable before the increment). Both the side effect and the evaluation itself are fully performed at that point. Then the execution goes on to process other subexpressions.
So you start out with the following:
= / \ i post-++ \ i
First, the left hand side of the assignment is evaluated, obtaining the location of the variable i. Let's say it's memory address 123, which I'll write as M[123]. There is no side-effect. So,
= / \ M[123] post-++ \ i
Next, the right-hand side of the assignment is evaluated. The right- hand side of the assignment is a post-increment, so the first step is to evaluate the variable to an lvalue. It's the same variable, so:
= / \ M[123] post-++ \ M[123]
Now that the operand to the post-increment has been evaluated, the post- increment itself is evaluated. This has two effects. It reads the value of M[123], and gets 1. That is the result of the expression. Also, right now (NOT delayed) it increments the value in that memory location as a side-effect. It does not increment the result of the expression; that's still 1.
= / \ M[123] 1
(as a side effect, now M[123] == 2)
Finally, the '=' operator has had both of its operands evaluated, so the operator itself gets evaluated. This again does two things. First of all, the result of the expression is the same as the right-hand side, which is 1. Second, the value of the RHS is stored into the memory location described by the LHS as a side effect. So,
1
(as a side effect, now M[123] == 1)
So as you can see, the value of i did briefly get assigned to 2, but was then overwritten by 1 again, explaining the fact that nothing appears to have changed. The order of those two writes to i -- the post-increment, and then the assignment -- is critical to understanding what happens here, and it's certainly wrong to say that the increment happens at some later time. As you can plainly see, the increment happened in exactly the same evaluation step as when the value of that subexpression was decided. It wasn't delayed in the slightest.
(As a side note, none of this applies to C or C++, despite the fact that they have operators that look identical. Both of those languages allow considerably greater flexibility to their implementations in terms of the result of expressions like this. We're just talking Java here.)
 Signature Chris Smith
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|