From §5.2.6/1 we have (emphasis is mine):
The value of a postfix ++ expression is the value of its operand. [ Note: the value obtained is a copy of the original value — end note ] The operand shall be a modifiable lvalue. The type of the operand shall be an arithmetic type other than cv bool, or a pointer to a complete object type. The value of the operand object is modified by adding 1 to it. The value computation of the ++ expression is sequenced before the modification of the operand object. With respect to an indeterminately-sequenced function call, the operation of postfix ++ is a single evaluation. [ Note: Therefore, a function call shall not intervene between the lvalue-to-rvalue conversion and the side effect associated with any single postfix ++ operator. — end note ] The result is a prvalue. The type of the result is the cv-unqualified version of the type of the operand. If the operand is a bit-field that cannot represent the incremented value, the resulting value of the bit-field is implementation-defined. See also [expr.add] and [expr.ass].
That is, the modification of the operand object is sequenced after the value computation of the ++
expression.
From §5.18/1 we have (emphasis is mine):
The assignment operator (=) and the compound assignment operators all group right-to-left. All require a modifiable lvalue as their left operand and return an lvalue referring to the left operand. The result in all cases is a bit-field if the left operand is a bit-field. In all cases, the assignment is sequenced after the value computation of the right and left operands, and before the value computation of the assignment expression. With respect to an indeterminately-sequenced function call, the operation of a compound assignment is a single evaluation. [ Note: Therefore, a function call shall not intervene between the lvalue-to-rvalue conversion and the side effect associated with any single compound assignment operator. — end note ]
assignment-expression:
conditional-expression
logical-or-expression assignment-operator initializer-clause
throw-expressionassignment-operator: one of
= *= /= %= += -= >>= <<= &= ^= |=
The assignment is also sequenced after the value computation of the right and left operands of the assignment operator.
Thus, if we consider the expression
i = i++;
we know from §5.2.6/1 that the side effect of the expression i++
, on the RHS of this assignment expression is sequenced after the value computation of i++
. And from §5.18/1 we know that the side effect corresponding to the assignment to i
on the LHS of the assignment operator is sequenced after the value computation of the right and left operands of the assignment operator.
But how do I show that these two side effects are unsequenced, in order to prove that the expression i = i++;
shows undefined behavior?
First, if A is not sequenced before B and B is not sequenced before A, then A and B are unsequenced (1.9/13). That's the definition of unsequenced. Second, if two side effects on a scalar object are unsequenced, the behavior is undefined (1.9/15). So unless you can find something that says that the post-increment and the assignment are sequenced (and you won't), the behavior is undefined.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With