Woozle Wuzzle
i = i++

A question was recently posted on the CJUG forum with regards to the following code:

    int i;
    i = 1;
    i = i++;
    System.out.println("i: " + i);

The poster wanted to know why in Java the result was 1 whereas in C / C++ the result was 2.

If you're like me, the first thing that popped in your head was: This person does not have a clear understanding of the postfix increment operator does. Let's tell him to go suck an egg and get a clue. But then I remembered back to the days when I didn't know what I was doing either and all of the kind and gentle people on usenet that steered me onto the path of knowledge.

In case you're having trouble getting over that hurdle, you can look at the problem as follows:

int[] a = { 0, 1, 2 };
int i;
i = 1;
a[i] = i++;
System.out.println("a[0]=" + a[0] + ", a[1]=" + a[1] + ", a[2]=" + a[2]);

which is slightly more palatable and results in the following:

a[0]=0, a[1]=1, a[2]=2

I'll spare the long winded answer to the reason why Java returns what it does and refer you to a Java forum posting. (Though if you want me to ramble on about it, just ask!) That takes care of the Java part, but what about C / C++? Well, if you didn't get all soft and squishy developing in Java all these years, you'll remember that the order of evaluation of operands of individual operators and the order in which side effects take place is unspecified in C / C++. You'll also start remembering about sequence points and all of that but before you begin to spasm uncontrollably, you'll remember that you've left all that behind you now. At the end of the day, the fact that the particular C / C++ compiler, runtime, etc resulted in 2 is simply luck of the draw. The expression is undefined. To quote Dale King:

...in C that statment might assign 0, 1, 42, -1 or any other value to i. It might crash your machine, erase your hard drive, or cause your computer to melt down. All would be acceptable results of executing that statement, since its behavior is undefined.

There is also Steve Summit's famous response which provides links to the C FAQ for more information.

Comments
Comment by ts at June 30, 2005 08:53 AM

"This person does not have a clear understanding of the postfix increment operator does. Let's tell him to go suck an egg and get a clue."

That's a rather foolish comment, since the question was about a difference in the results of the postfix increment operator across languages; a question about such a difference is quite independent of any knowledge of the operator at hand. The a[i] example you gave is irrelevant and misses the point, which concerns the value of the variable i after the statement is executed, not the value of i++, which is of course by definition the same as the value of i before the statement was executed. And the blog entry is as completely clueless as your own comments.

The issue here is not the obvious fact, probably well-known to the person that asked the question, that the value of i++ is the value of i before the increment, but rather the not at all obvious value of the variable i after the statement i = i++ is executed. That value depends on whether the increment of i occurs before or after the assignment. Which has nothing to do with the an understanding of the postfix operator, clear or not; the only way to know that is to read the JLS, which stipulates that the increment occurs first, thus i is left with the value of 1, not 2 ... but Gosling could just as well have specified it the other way around. As for C, that's the only thing you get right ... that it's unspecified. In some implementations the value will be 1, in some it will be 2, and in some it will be one or the other based on optimization flags. Nowhere, though, will it be anything else, as a practical matter of compiler design. As a former member of X3J11, the ANSI C standards committee, I can tell you that the widely seen comment about erasing your hard drive, which was oft used by committee members and certainly did not originate with Dale King, is a bit of a silly in-joke. Since the standard doesn't specify the behavior, then from *it's* point of view, the implementation could erase your disk drive ... *without being in violation of the standard*. But saying that that would be an "acceptable result" is plain stupid, a point that the standard makes oblique reference to via the phrase "quality of implementation".

 

Comment by ts at June 30, 2005 09:14 AM

Here's another point to further illustrate what's at issue. What's the value of i after i = 1; i = ++i; in C? This is *also* undefined, and in some implementations i might be 3, especially if i+1 had been calculated previously and is still in a live register. Why? Because i = ++i can be decomposed into RHS = i+1, LHS = RHS, and ++i, and the standard doesn't specify their order.

The C standard committee was largely made up of compiler vendors, whose marketing depends heavily on performance evaluation (aka benchmark cooking), and so the language definition goes out of its way not to invalidate optimizations. Java, OTOH, had a very different goal, of producing the same results in all implementations, so it nailed down everything, from the size of an integer to the order of evaluation to the (very bad) hash function for the String class. *That* is the answer to the question, not some juvenile strawman about not understanding the post-increment operator.

 

Comment by ts at June 30, 2005 09:46 AM

As another illustration of how off-base your comments and example are, consider the effect of each of the following in Java. Don't cheat; decide what they do *before* testing it in the compiler.

a[i++] = i;

a[i++] = i++;

a[i++] = ++i;

 

Comment by rgrzywinski at July 1, 2005 06:33 AM

WoW! Someone clearly woke up on the wrong side of the bed this morning and decided to use that fact to blast into me. While I certainly appreciate your insight into what initially appears to be a trivial problem, your other comments are simply out of place and had no reason to be posted.

My two statements: "If you're like me, the first thing that popped in your head was: This person does not have a clear understanding of the postfix increment operator does. Let's tell him to go suck an egg and get a clue. But then I remembered back to the days when I didn't know what I was doing either and all of the kind and gentle people on usenet that steered me onto the path of knowledge" are *clearly* a subtle attempt at humor. Why? Because anyone that has spent any time reading usenet posts knows that people are anything but "kind and gentle". In most cases all you get is a verbal lashing as to how ignorant and foolish you are (quite similar to your comments posted here though I am by no means saying that you are as brash as most usenet postings).

I will not bother to defend or clarify any of my other statements since you have obviously taken them in a manner that differs from the way that they were intended. I will only say that I apologize if they in any way offended you as that was not the intent.

Again, I certainly appreciate your insight into this interesting and non-trivial problem.

 

Comment by Jayaprabhakar Kadarkarai at June 6, 2007 01:22 PM

I think you will like the explanation that I have given here.

http://skeletoncoder.blogspot.com/2006/09/java-tutorials-i-i.html

This shows the exact Byte Codes, and illustrates step by step at the JVM level.

 

Comment by Sil at April 4, 2008 02:10 PM

TS was right in everything he posted... why did you felt offended? If know to little about something than don't try to answer just to brag you know something... You will only make things unclearer.

PS. You did not answer the question at all

 

Comment by rgrzywinski at April 5, 2008 06:54 AM

Hello Sil! Thanks for the comment.

If you can tell me in what way you don't think that I answered the question, I will be more than happy to elaborate for you.

 

Post a comment













Remember personal info?






Creative Commons License Unless otherwise expressly stated, all original material of whatever nature created by Rob Grzywinski and included in this weblog and any related pages, including the weblog's archives, is licensed under a Creative Commons License.