问题
As everyone knows, this loops through zero:
while (x-- > 0) { /* also known as x --> 0 */
printf("x = %d\n", x);
}
But x = x--
yields undefined behaviour.
Both examples need some 'return' value of x--
, which is not there I guess. How can it be that x-- > 0
is defined but x = x--
is not?
回答1:
Because in x = x--
you're modifying the value of x
twice without an intervening sequence point. So the order of operations is not defined. In x-- > 0
the value of x
is modified once, and it is clearly defined that result of evaluating x--
will be the value of x
before the decrement.
回答2:
I don't know where you got that idea about "need some 'return' value of x--, which is not there". Firstly, it is not exactly clear what you mean. Secondly, regardless of what you mean this doesn't seem to have anything to do with the source of undefined behavior in x = x--
.
x = x--
produces undefined behavior because it attempts to modify x
twice without an intervening sequence point. No "need" for any "return value" is involved here.
The underlying problem with x = x--
is that it has two side-effects that occur at undefined moments in undefined order. One side-effect is introduced by the assignment operator. Another side-effect is introduced by postfix --
operator. Both side-effects attempt to modify the same variable x
and generally contradict each other. This is why the behavior in such cases is declared undefined de jure.
For example, if the original value of x
was 5
, then your expression requires x
to become both 4
(side-effect of decrement) and 5
(side-effect of assignment) at the same time. Needless to say, it is impossible for x
to become 4
and 5
at the same time.
Although such a straightforward contradiction (like 4
vs 5
) is not required for UB to occur. Every time you have two side-effects hitting the same variable without intervening sequence point, the behavior is undefined, even if the values these side-effects are trying to put into the variable match.
回答3:
In order to understand this you need to have a basic understanding of sequence points. See this link: http://en.wikipedia.org/wiki/Sequence_point
For the =
operator there is no sequence point, so there is no guarantee that the value of x
will be modified before it is again assigned to x
.
When you are checking the condition in the while loop x-- > 0
, x--
is evaluated and the value is used in the relational operator evaluation so there is no chance of undefined behaviour because x
is getting modified only once.
回答4:
Just to add something to other answers, try reading this wikipedia page about sequence points.
回答5:
I suggest reading https://stackoverflow.com/a/21671069/258418. If you chuck together that =
is not a sequence point, and the compiler is free to interleave operations, as long as they are not separated by a sequence point from the answers linked by you, you see that i.e. the following two sequences would be legal:
load i to reg
increment i
assign reg to i
=> i has previous value of i
load i to reg
assign reg to i
increment i
=> i has value of previous value of i + 1
In general: avoid assigning (this includes modiying by pre/post ++/--) to the same variable twice in one expression.
来源:https://stackoverflow.com/questions/4924376/why-is-x-0-not-undefined-behaviour-while-x-x-is