I told you people would want to kill me for that one.
Consider this.
Here, i = 5 is an expression that evaluates to 5. Essentially, = is an operator with a side effect of assignment. Same idea with either ++i or i++. They are both operators with a side effect of assignment. Now consider:
You have 3 operators here, and according to that paragraph I quoted, when evaluating the expression (remember that the whole line is an expression that evaluates to the result getting assigned to i on the left) the order of the side effects of those 3 operators is undefined.
(There was some discussion in a compiler course I took on what that expression did. People came to the conclusion that it was undefined. Or maybe it was j = i++ + ++i; ?)
Here's another one for you:
i = 0;
j = i++ + i++ + i++;
What is the value of j? I just tried this with MSVC. When I tried it, I got 0.
Now try this:
i = 0;
j = ++i + ++i + ++i;
What is the value of j? I just tried this with MSVC, and I got 7. How does that work? So I took a look at the compiled code and here is what it did.
It incremented the value of i, and then stored it. (
++i + ++i + ++i).
Then it read i from memory and incremented it again. (++i +
++i + ++i).
Then it read i from memory, and added it to i from memory. (
++i + ++i + ++i).
Then it read i from memory and incremented it again. (++i + ++i +
++i).
Then it added that value to the sum of the previous 2. (
++i + ++i + ++i).
Then it performed the assignment to j.
Note how the effect of the first ++i was felt by the second ++i. Then the effect of both the ++i was felt by the third ++i. Ok, so this seems to follow exactly the method you've described so far. But is that surprising? No. MSVC obviously follows a particular method here. This seems to be the most obvious way of doing things, so no real surprise they've done it this way.
Ok, so now try:
i = 0;
j = i++ + ++i + ++i;
The result is 4. Try doing this one in a left to right order with ++ (pre or post) taking prescendence over +. You should get 5. Ok, now don't increment the i++ (post) until after j is assigned. You get 3. Ok, so now evaluate ++i, and then add that to i++, and then add the third term ++i. And then finish the increment from the ++i. You get 4. Go look at the assembly. This was the order in which is was done. It's not quite so obvious how that follows your set of rules now. The ++i on the RIGHT side of the first + took precendence over the i++ on the LEFT side of it. Clearly not left to right ordering here. It's also not right to left ordering, since that would give you 6.
Ok, now we try:
i = 0;
j = ++i + i++ + ++i;
The result is again 4. Taking a look at the assembly, the ++i on the LEFT is evaluated first. Then the i++ is evaluated (remember, it evaluates to the value before the increment) and added to that result. Then the final ++i is evaluated. The result is assigned to j. And then finally, the effect of i++ is done. Ok, so in this case, it was left to right ordering. Or was it? It could equally well have been right to left ordering here and you'd get the same result. Not really any way to tell here.
Next up:
i = 0;
j = i++ + i++ + ++i;
The result is 1. In this case, the (i++ + i++) was performed first. Simple left to right ordering in this case.
Produces a compile error. "needs l-value". As does
(Not too surprising)
Results in 1.
Also, interestingly enough.
i = 0;
j = (++i + ++i) + ++i;
Evaluates to 7.
i = 0;
j = ++i + (++i + ++i);
Evaluates to 9.
Does that last part bother anyone else here? On closer inspection, the 3 increments are performed before any of the additions on that last example. I guess I can understand that.
As a final set of examples:
i = 0;
j = ++i = ++i + ++i;
i = 0;
j = ++i = (++i + ++i);
i = 0;
j = (++i = ++i) + ++i;
The results are 6, 6, and 6. (But the values of i are 6, 6 and 3).
So yeah, MSVC has probably followed a certain standard (even if the C++ specs don't specify one here). It doesn't mean one particular compiler is going to produce undefined results. Of course it won't. Not unless it's using random numbers during the compilation process. (I'm sure that would bother most people). But it does mean that a different compiler (that follows the C++ specs) CAN produce different results for the same code. It doesn't mean it will, especially not if there is an obvious way of doing things. But as for the standard that MSVC uses, the best I can determine is the following. The ++i's take effect on the i in a left to right order, and if an expression can be evaluated in a left to right order following the precendence rules, then it is. Otherwise, the ++i's will continue taking effect and the expressions are evaluated afterwards. The assignments seem to take place after the ++i's, and then the i++'s seem to take effect after the assignments.
Ay any rate, I don't buy your simple left to right ordering theory. Not without extra rules to clear up some issues. Nor do I trust any expressions where a variable is used more than once on the same line involving ++ (pre), ++ (post) or =.