R
Robin Haigh
Ben Pfaff said:Ben said:(e-mail address removed) writes:
Any compiler that compiles p = p->next = q as storing into p
before fetching p->next is simply broken. Operands are
evaluated before the operator they're operands for, and
operators are evaluated before they produce a value--that's
just how C semantics work (in a C abstract machine of course).
Do you have any citations to back up your assertions?
"Evaluation of an expression may _produce_ side effects."
"[At sequence points,] all side effects of _previous_
evaluations shall be complete [...]."
"In the abstract machine, all expressions are evaluated
_as specified by the semantics_."
OK.
"[An operator] may specify an operation to be performed
(which _in turn_ may _yield a value_ [...], _produce_ a
side effect, or some combination thereof) [...]."
I don't see anything about ordering there.
"The syntax specifies the precedence of operators _in the
evaluation of_ an expression [...]."
Precedence != ordering.
Precedence puts unavoidable contraints on ordering, because it establishes
which subexpressions are the operands of other expressions.
"[Except ...], _the order of evaluation of subexpressions_
and _the order in which side effects take place_ are both
unspecified." (Not "order of A and B" but "order of A" and
"order of B".)
I don't think that typographical distinction is a good one to
hinge an argument on. "the order of" could be repeated just for
clarity of exposition. Even if the typography is significant
here, I don't think it gets you where you want to go.
Keeping these in mind, read through section 6.5, noting
which paragraphs are marked "Semantics". Expressions
are evaluated "as specified by the semantics".
OK. Let's look at section 6.15.6 "Assignment operators":
3 ... The side effect of updating the stored value of the
left operand shall occur between the previous and the
next sequence point.
4 The order of evaluation of the operands is
unspecified. ...
In p = p->next = q there are two assignments, so 6.15.6 has to be applied to
each of them separately.
4 The order of evaluation of the operands is
unspecified. ...
Well each assignment has left and right operands, and in each case it makes
no difference whether we evaluate the left before the right or vice versa.
Nobody is claiming otherwise. It's a non-issue.
But nothing here contradicts the fact that one assignment must be evaluated
before the other, for the simple reason that the value of one is an operand
of the other. "Evaluated" here means fully evaluated according to the
semantics -- the abstract machine has no optimiser and no licence to
simplify, so just doing enough to ascertain the value doesn't qualify.
3 ... The side effect of updating the stored value of the
left operand shall occur between the previous and the
next sequence point.
The wording is very specific. "The side effect of updating the stored
value" (of an object referenced by an lvalue) doesn't extend to computing
the lvalue in question. The evaluation of the left operand of an assignment
is not part of the side effect.
The timing of the side effect is only an issue for the outer assignment.
And the quote above only puts outer limits on when the side effect occurs.
It doesn't say that the side effect may occur at any time between the
sequence points -- of course that would be silly, because the new value has
to be computed before it can be stored, so the side effect cannot occur
before the evaluation of the expression which provides the new value.
Another constraint on ordering that is too obvious to be stated, but is not
overridden by any wording.
It seems pretty clear that both the order of evaluation of the
operands and the time at which the result is stored are both
rather unconstrained.
That's an interesting approach: two insignificant details are left
unspecified, so it must be saying "anything goes"