a[i] = foo();
Here it is unspecified whether foo
or a[i]
is evaluted first. In the new C++11 wording, the two evaluations are unsequenced. That alone doesn't cause undefined behaviour, though. It is when there are two unsequenced accesses to the same scalar object, at least one of which is writing, where it does. That's why a[i] = i++;
is UB.
The difference between these two statements is that a call to foo()
does introduce a sequence point. C++11 wording is different: executions inside a called function are indeterminately sequenced with respect to other evaluations inside the calling function.
This means there's a partial ordering between a[i]
and i++
inside foo
. As a result, either a[0]
or a[1]
will get set to 0, but the program is well defined.