Does this C99 code produce undefined behavior?
No. It will not produce undefined behavior. a[0]
is modified only once between two sequence points (first sequence point is at the end of initializer int a[3] = {0, 0, 0};
and second is after the full expression a[a[0]] = 1
).
It does not mention reading an object to determine the object itself to be modified. Thus this statement might produce undefined behavior.
An object can be read more than once to modify itself and its a perfectly defined behavior. Look at this example
int x = 10;
x = x*x + 2*x + x%5;
Second statement of the quote says:
Furthermore, the prior value shall be read only to determine the value to be stored.
All the x
in the above expression is read to determine the value of object x
itself.
NOTE: Note that there are two parts of the quote mentioned in the question. First part says: Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression., and
therefore the expression like
i = i++;
comes under UB (Two modifications between previous and next sequence points).
Second part says: Furthermore, the prior value shall be read only to determine the value to be stored., and therefore the expressions like
a[i++] = i;
j = (i = 2) + i;
invoke UB. In both expressions i
is modified only once between previous and next sequence points, but the reading of the rightmost i
do not determine the value to be stored in i
.
In C11 standard this has been changed to
6.5 Expressions:
If a side effect on a scalar object is unsequenced relative to either a different side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined. [...]
In expression a[a[0]] = 1
, there is only one side effect to a[0]
and the value computation of index a[0]
is sequenced before the value computation of a[a[0]]
.