-1

A discussion arose around the C statement x = b[i] + i++; and its definedness.

The argument for said statement to be undefined goes something like this:

§ 6.5 of C99 states:

[…] the order of evaluation of subexpressions and the order in which side effects take place are both unspecified.

Thus it is not guaranteed that i is incremented after it is used in the subscript operator as index of the array.

However, I interpret said specification differently.

§ 6.5 of C99 additionally states:

Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be read only to determine the value to be stored.

§ 5.1.2.3 of C99 states:

At certain specified points in the execution sequence called sequence points, all side effects of previous evaluations shall be complete and no side effects of subsequent evaluations shall have taken place.

A list of sequence points is given in annex C and only the following matches the statement in question IMHO.

The end of a full expression

The evaluation of b[i] (the value of element i of b) and that of i++ (just i) can happen in any order before the addition (and evaluation of =, which is the value of the RHS) is done. However, the side effects of the whole statement are deferred until after all these evaluations because that's the only sequence point. In this case the side effects are the change of x and the increment of i.

Who is right? Are there additional paragraphs relevant for the argument? Is it any different in C++?

stefanct
  • 2,503
  • 1
  • 28
  • 32
  • 3
    It is undefined. The side effects are not deferred. They are *guaranteed* to take place after the sequence point, but not mandated *not* to take place before. – Eugene Sh. May 30 '18 at 15:20
  • Would the downvoter please explain his/her vote so that we can improve the question? – stefanct May 31 '18 at 09:39

3 Answers3

2

Side effects don't have to be deferred until the sequence point -- they may be applied immediately upon evaluation. Or not.

C 2011 has some slightly different (more precise) language:

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.

C 2011, §6.5 ¶2

i++ has a side effect on i, b[i] uses i in a value computation, and the two subexpressions are unsequenced relative to each other (i.e., there is no intervening sequence point). Thus, the behavior of b[i] + i++ is undefined.

John Bode
  • 119,563
  • 19
  • 122
  • 198
2

Your quotation from section 6.5 is the relevant one:

Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression. [In that event, f]urthermore, the prior value shall be read [between those sequence points] only to determine the value to be stored.

(Clarifications mine.)

In your statement, the value of i is both modified and used as an index into b. Your statement contains no internal sequence points, so these effects must occur between the same pair of sequence points. The statement therefore violates the quoted requirement. Section 4, paragraph 2 then applies:

If a ''shall'' or ''shall not'' requirement that appears outside of a constraint is violated, the behavior is undefined. [...]

That's all there is to it. No other considerations are required. Your argument about actual order of operations is completely irrelevant.

Nevertheless, your claim that

the side effects of the whole statement are deferred until after all these evaluations because that's the only sequence point.

reflects a serious misunderstanding of sequence points. Sequence points do not represent times when things happen, but rather boundaries between which things happen. Not only are side effects not deferred to the next sequence point, they are far less constrained (by the standard) than operations involved in computing the values of expressions.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
1

§6.5.2.4 states

The side effect of updating the stored value of the operand shall occur between the previous and the next sequence point.

Just like Eugene's comment suggested. In case this is not clear enough the statement cited in the question in § 6.5 (1)

the prior value shall be read only to determine the value to be stored.

is violated directly as well. The value of i is not just read to determine the value after incrementing but also as operand of the subscript operator.

This question and its accepted answer might give additional insights as it discusses the sequence points introduced by the , operator and its interaction with the potential UB-provoking behavior of assignments.

stefanct
  • 2,503
  • 1
  • 28
  • 32