First sentence:
Between the previous and the next point in the sequence, the object must have its stored value, changed no more than once by evaluating the expression.
clear enough. The language does not impose an evaluation order on subexpressions if there is no sequence point between them, and instead of requiring some unspecified evaluation order, it is said that changing an object twice leads to undefined behavior. This allows for aggressive optimization, while maintaining the ability to write code following the rules.
Next suggestion:
In addition, the previous value should only be read to determine the stored value.
seems unintuitive at first (and second) look; why does the purpose for which the value is read affect whether the expression defined behavior?
But what it reflects is that if the sub-expression of B depends on the result of the sub-expression of A, then A needs to be evaluated before B can be evaluated. Standards C90 and C99 do not explicitly state this.
A more obvious violation of this sentence, as shown in the footnote example, is as follows:
a[i++] = i;
Assuming that a is a declared array object, and i is a declared whole object (without a pointer or macro), no object changes more than once, so it does not violate the first sentence. But the i++ score on the LHS determines which object should be changed, and the i grade on the RHS determines the value that will be stored in this object - both the relative order of the read operation on the RHS and the write operation on the LHS are not defined. Again, the language might require subexpressions to be evaluated in some unspecified order, but instead, it left all the behavior undefined to provide more aggressive optimizations.
In your example:
int i = 0, *a = &i; a[i] = i;
the previous value i read both to determine the stored value, and to determine which object it will store. Since a[i] refers to i (but only because i==0 ), changing the value of i would change the object to which lvalue a[i] refers. In this case, the value stored in i matches the value that was already written there ( 0 ), but the standard does not make an exception for stores that store the same value. I believe the behavior is undefined. (Of course, the example in the standard was not intended to cover this case; it implies that a is a declared array object that is not associated with i .)
As for the example permitted by the standard:
int a[10], i = 0; a[i] = i;
one could interpret the standard to say that it is undefined. But I think that the second sentence, referring to the “previous value”, refers only to the value of the object that was modified by the expression. i never changes expression, so there is no conflict. The value of i used both to determine the object to be changed by the purpose, and for the value that should be stored there, but this is normal, since the value of i never changes. The value of i not a "prior value", it is just a value.
In the C11 standard, there is a new model for such an expression to evaluate an expression, or rather, it expresses the same model in different words. Instead of “sequence points,” he says that side effects are sequenced before or after each other or illogical with respect to each other. It clearly states that if sub-expression B depends on the result of sub-expression A, then A must be evaluated before B can be evaluated.
In project N1570 , section 6.5 says:
1 An expression is a sequence of operators and operands that defines the calculation of a value or designates an object or function, or that generates side effects or performs combinations of them. The calculation of the values of the operands of the operator is ordered before the calculation of the value of the result of the operator.
2 If the side effect of a scalar object is independent of either another side effect on the same scalar object, or the calculation of a value using the value of the same scalar object, the behavior is undefined. If there are several valid orders of expression subexpressions, the behavior is undefined if such an unpredictable side effect occurs in any of the orders.
3 The grouping of operators and operands is indicated by the syntax. Except as noted below, side effects and the calculation of sub-expression values are not relevant.