I have studied sequence points (C99) and sequenced before /unsequenced (C17) and some other posts here in SO about this topic and its relation with undefined behaviour.
I think with C99 its ultra-clear that i=i++; and i=++i; both result in undefined behaviour, but according to C17 (or even C23) we have this:
If a side effect on a scalar object is unsequenced relative to either a different side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined. If there are multiple allowable orderings of the subexpressions of an expression, the behavior is undefined if such an unsequenced side effect occurs in any of the orderings.
And therefore, this:
i=i++;
Results in undefined behaviour because we have here to side effects the postfix ++ operator and the assignment, and according to the answer of haccks in this post Why are these constructs using pre and post-increment undefined behavior?, we know that both side effects are unsequenced relative to each other so this results in undefined behaviour, but what about this:
i=++i;
At least for what I know here the incremented value of i should be used in the full expression, so we again have two side effects but now the side effect result of the pre-increment operator must be sequenced before the side effect result of the assignment operator, right?
And now my theory why, according to C11/C17/C23, "i=++i; is undefined behaviour is because the side effect result of the pre-increment operator is unsequenced relative to the value computation of "i" in the LHS right?
From https://port70.net/~nsz/c/c11/n1570.html#6.5.3.1p2 or https://port70.net/~nsz/c/c99/n1256.html#6.5.3.1p2 :
From https://port70.net/~nsz/c/c11/n1570.html#6.5.16.2p3 or https://port70.net/~nsz/c/c99/n1256.html#6.5.16.2p3 :
So we have
i = (i = i + 1);, where the twoiare evaluated once.From https://port70.net/~nsz/c/c11/n1570.html#6.5.16p3 or https://port70.net/~nsz/c/c99/n1256.html#6.5.16p3 :
Now we start the engine. Let's mark them
i₁ = (i₂ = i₃ + 1);just to know to whichiI am referring to.So updating
i₂is sequenced after computationi₃ + 1.And updating
i₁is sequenced after computationi₂ = i₃ + 1.But! Updating
i₁and updatingi₂are unsequenced. We do not know "when" the side effect of updatingi₂will happen relative to the value computation of the value of the expressioni₂ = i₃ + 1.i₂could be updated right after, or could be updated at the next sequence point, which is at;.But there is no sequence point after
i₂ = i₃ + 1. Updating ofi₁is after computingi₂ = i₃ + 1, but is not sequenced with updatingi₂. At the time of updatingi₁the side effect of updatingi₂is still "hanging", "to do". Because updatingi₁andi₂is unsequenced, this is why it's undefined behavior.