问题
I understand that this is undefined behavior:
int i = 0;
int a[4];
a[i] = i++; //<--- UB here
because the order of evaluation of i
for the left hand side and the right hand side are undefined (the ;
is the only sequence point).
Taking that reasoning a step further it seems to me that this would be undefined unspecified behavior:
int i = 0;
int foo(){
return i++;
}
int main(){
int a[4];
a[i] = foo();
return 0;
}
Even though there are a few sequence points on the right hand side of the =
as far as I understand it is still undefined unspecified whether f()
or a[i]
is evaluated first.
Are my assumptions correct? Do I have to take painstaking care when I use a global or static variable on the left hand side of an assignment that the right hand does not under any circumstances modify it?
回答1:
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.
回答2:
a[i] = i++;
This is undefined behavior because the value of i
is both modified and accessed between two sequence points (and the access is not directly involved in the computation of the next value of i
).
This is also unspecified behavior, because the order of evaulation is unspecified (the increment of i
can happen before or after using i
as the index into a
).
When you introduce a function call, like :
a[i] = foo();
the function call introduces two further sequence points : one before the function is entered, and one after the function has returned.
This means that the increment of i
inside the function is surrounded by two sequence points, and does not cause undefined behavior.
It is still unspecified behavior though whether the function call will be done before using i
as an index on the left-hand side of the assignment, or after.
来源:https://stackoverflow.com/questions/22940686/is-one-side-of-an-assignment-sequenced-before-the-other-in-c