Win a copy of The Way of the Web Tester: A Beginner's Guide to Automating Tests this week in the Testing forum!

# Explanation for i = i++;

Nick Widelec
Ranch Hand
Posts: 226
Hi,
Is there anybody that can actually explain why does not change the value stored in "i"?

I understand the post increment thing. That's why once (), the value gets assigned to the left of the equal. it should get incremented of one as there was still the post increment i++ operand going on.
To whom who says: Ok it first the value gets assigned (the old value as is the post increment being used), and then the value of i gets incremented. But the operand i++ also assign the value to the variable does not only increment the value.

The value 0 gets stored in i

Thanks in advance for the responses.

Widelec.

Stevens Miller
Bartender
Posts: 1313
25
You're not the only one who ever asked this, but I think most people who ask it do so because they believe the increment happens after the assignment. That's not really the case. What happens is that the increment happens during the evaluation of the expression, but the postfix increment operator is defined to return the original value. That is, you tend to think it is happening like this:

1. Assign value of x to itself.
2. Increment x.

But it's really more like this:

1. Make a copy of x.
2. Increment x.
3. Return the copy.
4. Assign the copy of x to itself.

Here's a wordier explanation you may like better, lifted from a Web site:

The reason it behaves as observed is because of the interaction between the operator precedence and the odd "return value" of the ++ operator.
The postfix increment happens first (see your favorite copy of the operator precedence chart); but postfix, by definition, returns the previous value of the variable. So that "return value" is not "original x plus one", but instead just "original x" (x, at this point, actually contains the incremented value). This returned value is then assigned to x, which overwrites what the ++ did in the first place. IOW, in the expression x=x++, the incremented value is lost, overwritten by the assignment that happens last.

You can think of ++ as a method like this:

int postfixIncrement() {
int result = x;
x = x + 1;
return result;
}
Then "x=x++" is rewritten as "x = postfixIncrement()" and the result is a little more intuitive.

Another perspective on it:

x = 1;
x = x++;
This translates to the following:

1) x is assigned the value 1.
2) x++ is performed, and its value is returned as x:
2a) x is assigned x+1, IOW x is assigned value 2
2b) Value 1 is returned to the expression.
3) x = (...) is performed:
3a) x is assigned the value from 2b, which is 1
So, after all is said and done, the value assigned to x is 1.

(I have lifted this, instead of simply linking to it, because the full text begins by treading dangerously close to saying this is a stupid question, which it's not.)

Note that C++ programmers make a big deal (some, anyway) about the implications of this, because the postfix and prefix increment operators can be overridden overloaded in C++. To avoid astonishing the next programmer to use your overridden overloaded postfix increment operator, you need to have it return a copy of the object it is applied to. This means making a copy of the object, which can imply significant overhead, especially in the innermost loop of some code. Applied to native integer types, there is probably no difference, but (some) C++ programmers will ding you for it anyway. In Java, I am guessing there might be a slight improvement when you use ++i over i++, but I'd have to look at some bytecode to know if the compiler optimizes the difference away.

Hope that helps.

Stevens Miller
Bartender
Posts: 1313
25
Here's a short example that illustrates how the increment is applied before the addition takes place:

Believe it or not, this program outputs "1" to your console. At line 8, the increment is evaluated first, changing i from 0 to 1. The increment operator returns the original value of i, which is 0. That value is then added to the value in i, which means that is 0 + 1 is assigned to j, so the value in j is 1 after line 8.

Campbell Ritchie
Sheriff
Posts: 50749
83
Stevens Miller wrote: . . . lifted from a Web site:
. . .
(I have lifted this, instead of simply linking to it, because the full text begins by treading dangerously close to saying this is a stupid question, which it's not.)
. . .
My, not only is that other website rude, but it also falls into the trap of thinking that people know about C operators. In fact C doesn’t know about C operators, and the behaviour of i++ is not strictly defined in C. I once tried this in C with three different compilers:Two printed 4 and one printed 5

As you said, this is a common problem, which causes no end of confusion to beginners, and we have an FAQ about it.
By the way: when you said overriding of operators in C++, didn’t you mean to say overloading?

Jesper de Jong
Java Cowboy
Saloon Keeper
Posts: 15571
46

Nick Widelec
Ranch Hand
Posts: 226
Thanks everybody for the prompt and thorough response!
Now I am clear about the issue.

Widelec.

Stevens Miller
Bartender
Posts: 1313
25
Campbell Ritchie wrote:My, not only is that other website rude, but it also falls into the trap of thinking that people know about C operators.

I've noticed that trap catches a lot of people, including the authors of most of my "Have Fun with Java" books. The good ones use boxes and other layout gimmicks to let you skip (or not) the points where they make a comparison to C (or C++). I am guessing there may have been a time when most people learning to program in Java already knew some C. But, I am also guessing those days are fading, if not gone already. What's interesting is that the "Have Fun with Java" books tend to make comparisons to C/C++ in ways that (to varying degress) subtly show Java to be the superior language, while my "Real Programmers Use C/C++" books find remarkable ways to show precisely the opposite thing. Go figure, eh?

In fact C doesn’t know about C operators, and the behaviour of i++ is not strictly defined in C.

True, and I admit I didn't know this myself until studying up on the difference in C++ (not "C/C++") between postfix and prefix incrementing recently for different reasons. Just as you say, it turns out that the increment operator's effect is not fully defined when you use it in some of the ways we've been kicking around here (like on a variable that appears more than once in an lvalue). I believe that, in C++, its behavior is more thoroughly defined, as it is in Java.

By the way: when you said overriding of operators in C++, didn’t you mean to say overloading?

Yes. For some reason, when discussing overloaded C++ operators (the existence of which, to be mild about it, I regard as the most convincing proof available that Satan is an active force in our world today), I almost always make that mistake. I have corrected edited that mistake in my post. Thanks for the backstop. (Before anyone dings me for it, I know that "+" is overloaded in Java; but that's overloading in a good way. )

BTW, while it isn't exactly rude, even my beloved Horstmann & Cornell couldn't resist taking a pot-shot at That Other Language in "Core Java," where they say this:
Of course, while it is true that the ++ operator gives the C++ language its name, it also led to the first joke about the language. C++ haters point out that even the name of the language contains a bug: "After all, it should really be called ++C, because we only want to use a language after it has been improved."

Matthew Brown
Bartender
Posts: 4568
9
Stevens Miller wrote:For some reason, when discussing overloaded C++ operators (the existence of which, to be mild about it, I regard as the most convincing proof available that Satan is an active force in our world today)

I think I've mentioned it before, but my ideal language would be defined in such a way that I could define overloaded operators, but other people couldn't .

(It can be done well. I remember using a C++ matrix algebra library which had nailed it. Standard arithmetic operators behaved exactly as you'd expect to if you knew matrix algebra, plus there were a couple of additional useful and natural feeling ones like ! for inverse and ^ for vector product).

Winston Gutkowski
Bartender
Posts: 10527
64
Matthew Brown wrote:I think I've mentioned it before, but my ideal language would be defined in such a way that I could define overloaded operators, but other people couldn't .

Hear, hear. Mind you, there's quite a few design-y things you could apply that principle to...

Winston

Campbell Ritchie
Sheriff
Posts: 50749
83
Agree about overloading things yourself. There is another operator which is overloaded: - which might mean subtraction or sign‑change. &|^ are bitwise operators overloaded to operate on booleans.

And welcome to the Ranch, Nick Widelec

Stevens Miller
Bartender
Posts: 1313
25
Matthew Brown wrote:(It can be done well. I remember using a C++ matrix algebra library which had nailed it. Standard arithmetic operators behaved exactly as you'd expect to if you knew matrix algebra, plus there were a couple of additional useful and natural feeling ones like ! for inverse and ^ for vector product).

That actually does sound like someone got it right. Of course, carried to extremes, you can end up with some pretty cryptic elegant stuff.

Stevens Miller
Bartender
Posts: 1313
25
Winston Gutkowski wrote:
Matthew Brown wrote:I think I've mentioned it before, but my ideal language would be defined in such a way that I could define overloaded operators, but other people couldn't .

Hear, hear. Mind you, there's quite a few design-y things you could apply that principle to...

I get around that, sometimes, by remembering that, in 1787, representatives of the United States gathered to revise The Articles of Confederacy. You know, patch them up a bit, so they had fewer bugs. What they did went something like this:

1. Open "The Articles of Confederacy"
2. Edit / Select All
3. Cut
4. <insert new text>
5. File / Save as "The Constitution of The United States"
6. File / Close

While they were criticized for overreaching at the time, their work has generally received positive reviews, and it is widely agreed now that it was a good move.

So, when handed crap code, I always ask if I am allowed to revise it where I can see obvious opportunities for improvement. The answer tends, usually, to be something like, "Yeah, sure, whatever, so long as you make the deadline."

Then, I simply follow the example set by my forebears, and things tend to work out pretty well from then on.