5

Can someone please explain whether i = x[i]++; lead to undefined behavior?

Note: x[i] and i are not both volatile and x[i] does not overlap i.

There is C11, 6.5 Expressions, 2 (emphasis added):

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. If there are multiple allowable orderings of the subexpressions of an expression, the behavior is undefined if such an unsequenced side effect occurs in any of the orderings. 84)

As I understand:

  • there is no "different side effect on the same scalar object"
  • there is no "value computation using the value of the same scalar object"

Are there "multiple allowable orderings"?

Overall: how can the i = x[i]++; be interpreted w.r.t. sequence points, side effects, and undefined behavior (if any)?


UPD. Conclusion: the i = x[i]++; leads to 2 side effects:

  1. "the value of the operand object is incremented" (Postfix increment)
  2. "updating the stored value of the left operand" (Assignment operators)

The Standard does not define the order in which the side effects take place.

Hence, per C11, 4. Conformance, 2:

Undefined behavior is otherwise indicated in this International Standard by the words ‘‘undefined behavior’’ or by the omission of any explicit definition of behavior.

Experiments show that GCC/LLVM/ICC have order 1-2, while MSVC (and some others) have order 2-1.


Extra (speculating): why not making it unspecified behavior? Example: "an example of unspecified behavior is the order in which the side effects take place"?

pmor
  • 5,392
  • 4
  • 17
  • 36

3 Answers3

2

If it were true that

  • there is no "different side effect on the same scalar object"
  • there is no "value computation using the value of the same scalar object"

(in every allowed ordering of the subexpressions), then the provision you cite would present no particular issue. That is, the antecedent of its "if" would not hold, so the consequence of that "if" (undefined behavior) would not be asserted.

However, there is both a side effect on i and a value computation using the value of i. The former is the side effect of the assignment, and the latter is the value computation of x[i]++. This is not a problem, however, because, for all forms of assignment,

The side effect of updating the stored value of the left operand is sequenced after the value computations of the left and right operands.

(C17 6.5.16/3)

Also, for completeness,

The value computations of the operands of an operator are sequenced before the value computation of the result of the operator.

(C17 6.5/1)

Thus, the assignment's side effect on i is sequenced after the value computation of x[i]++, which is sequenced after the evaluation of i.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
  • For `i = x[i]++;` what is the order of the following side effects: "the value of the operand object is incremented" (Postfix increment) and "updating the stored value of the left operand" (Assignment operators)? Can this order (if any) be deduced? – pmor Apr 12 '22 at 15:46
  • @pmor, those side effects are not sequenced relative to each other. That's why `i = i++` and `i = ++i` have undefined behavior. – John Bollinger Apr 12 '22 at 15:51
  • Does "those side effects are not sequenced" imply "the behavior is undefined"? Note that in case `i = x[i]++;` the updated object `x[i]` is not the same as the the left operand `i` of the assignment operator. For example: is there a guarantee that after `i = x[i]++;` the `x[i]` will be incremented? – pmor Apr 12 '22 at 16:12
  • 1
    @pmor, do you have some basis to suppose that the behavior would be undefined? Having side effects or other behaviors that are not sequenced relative to each other is not inconsistent with well-defined behavior in the general case. – John Bollinger Apr 12 '22 at 16:18
  • I recall that ordering issues (e.g. "the order in which the arguments to a function are evaluated") cause _unspecified_ behavior. One more question: does "value computations of the left and right operands" (Assignment operators) take into account the side effects (e.g. "the value of the operand object is incremented" (Postfix increment))? – pmor Apr 12 '22 at 16:59
  • Why not (speculating): "an example of unspecified behavior is the _order in which the side effects take place_"? – pmor Apr 12 '22 at 17:53
  • @pmor, unspecified behavior is an entirely different thing from undefined behavior. Also, in the specific case of function arguments, the relative order in which they are evaluated is unspecified (in particular, those evaluations are unsequenced relative to each other), but that doesn't "cause" any other unspecified behavior. – John Bollinger Apr 12 '22 at 18:27
  • 2
    Anyway, @pmor, no, the "value computation" of an expression means exactly and only what it says: computing the value to which the expression corresponds. That does not include applying any side effects produced by the expression. – John Bollinger Apr 12 '22 at 18:27
1

There is a value computation using the value of the same scalar object. x[i] uses the value of i.

Since C11, there is a sequence relation in assignment.

The side effect of updating the stored value of the left operand is sequenced after the value computations of the left and right operands.

(C11 6.5.16/3)

Prior to then the way the standard discussed expressions was looser. It did not describe a sequenced before relation. Instead we have:

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.

You aren't reading the value "other than to determine the value to be stored", so the behaviour is defined.

(C99 6.5/2)

Caleth
  • 52,200
  • 2
  • 44
  • 75
  • Comments are not for extended discussion; this conversation has been [moved to chat](https://chat.stackoverflow.com/rooms/243919/discussion-on-answer-by-caleth-does-i-xi-lead-to-undefined-behavior). – Machavity Apr 15 '22 at 01:23
1

Imagine:

i = 3;
x[] = {1, 1, 1, 1, 1};

So, x[i] equals 1, x[i]++ equals 2 and x becomes {1, 1, 2, 1, 1}, and i becomes 1.

Why would there be any undefined behaviour?

Dominique
  • 16,450
  • 15
  • 56
  • 112