Is the behaviour of i = i++ really undefined?
No, we don't use the term "undefined behavior" when it can simply lead to more than one arithmetical result. When the behavior is limited to different arithmetical results (or, more generally, to some set of predictable results), it is typically referred to as unspecified behavior.
Undefined behavior means completely unpredictable and unlimited consequences, like formatting the hard drive on your computer or simply making your program to crash. And i = i++
is undefined behavior.
Where you got the idea that i
should be 4 in this case is not clear. There's absolutely nothing in C++ language that would let you come to that conclusion.
1. No, the result will be different depending on the order of evaluation. There is no evaluation boundary between the increment and the assignment, so the increment can be performed before or after the assignment. Consider this behaviour:
load i into CX
copy CX to DX
increase DX
store DX in i
store CX in i
The result is that i
contains 3
, not 4
.
As a comparison, in C# there is a evaluation boundary between the evaulation of the expression and the assignment, so the result will always be 3
.
2. Even if the exact behaviour isn't specified, the specification is very clear on what it covers and what it doesn't cover. The behaviour is specified as undefined, it's not unspecified.
In C and also in C++, the order of any operation between two sequence points is completely up to the compiler and cannot be dependent on. The standard defines a list of things that makes up sequence points, from memory this is
- the semicolon after a statement
- the comma operator
- evaluation of all function arguments before the call to the function
- the && and || operand
Looking up the page on wikipedia, the lists is more complete and describes more in detail. Sequence points is an extremely important concept and if you do not already know what it means, you will benefit greatly by learning it right away.
The phrase, "…the final value of i
will be 4 no matter what the order of evaluation…" is incorrect. The compiler could emit the equivalent of this:
i = 3;
int tmp = i;
++i;
i = tmp;
or this:
i = 3;
++i;
i = i - 1;
or this:
i = 3;
i = i;
++i;
As to the definitions of terms, if the answer was guaranteed to be 4, that wouldn't be unspecified or undefined behavior, it would be defined behavior.
As it stands, it is undefined behaviour according to the standard (Wikipedia), so it's even free to do this:
i = 3;
system("sudo rm -rf /"); // DO NOT TRY THIS AT HOME … OR AT WORK … OR ANYWHERE.