-5

I have read about undefined behaviour.

This Link says a[i] = a[i++] leads to undefined behaviour.

But I don't understand why the output of

int arr[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int i = 0;
cout << arr[++i] + ++i << " " << i;

is 3 2

and the output of

int arr[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int i = 0;
cout << ++i + arr[++i] << " " << i;

is 4 2

M.M
  • 138,810
  • 21
  • 208
  • 365
RaKo
  • 49
  • 1
  • 2
  • 11
  • 1
    Have you also already read this https://stackoverflow.com/questions/949433/why-are-these-constructs-using-pre-and-post-increment-undefined-behavior ? – Bob__ Oct 30 '21 at 00:44
  • `a[i] = a[i++]` is well-defined since C++17 – M.M Oct 30 '21 at 01:17
  • 1
    in any case a C++ question should not be closed as duplicate of C question, since the sequencing rules are different' – M.M Oct 30 '21 at 01:22
  • I have read about UB. It should apply when you assign and increment at the same time. But here, there is no assignment. Instead the value of i is incremented and printed (not assigned) using cout. – RaKo Oct 30 '21 at 01:37
  • "It should apply when you assign and increment at the same time." - not necessarily. Take a look at the 6th example of [undefined behavior in C and C++](https://en.wikipedia.org/wiki/Undefined_behavior#Examples_in_C_and_C++): no assignment. – enzo Oct 30 '21 at 01:55
  • @enzo wikipedia is not a good reference, and none of the examples cover the code in this question anyway – M.M Oct 30 '21 at 04:00
  • @M.M That's why Wikipedia itself have [references](https://en.wikipedia.org/wiki/Undefined_behavior#References). My comment was referring to the OP comment stating that undefined behavior only happens on assignment, which is not true. – enzo Oct 30 '21 at 04:08

1 Answers1

2

Firstly - a[i] = a[i++] is well-defined since C++17. The sequencing rules were considerably tightened in that revision of the Standard, and the evalution of the right-hand side of an assignment operator is sequenced before the evaluation of the left hand side, meaning that all side-effects of the right-hand side must be complete before evaluation of the left-hand side begins.

So that code is equivalent to a[i+1] = a[i]; ++i;


Since C++17, the << operator also has left-right sequencing, i.e. the left operand is sequenced before the right operand.

Now, ++i is defined as i+=1 and similar considerations as above apply to the evaluation of the compound assignment operator. The ++i occurs "atomically" we could say.

However, the + operator is still unsequenced, this is defined by [intro.execution]/17:

Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced.

[...]

If a side effect on a memory location is unsequenced relative to either another side effect on the same memory location or a value computation using the value of any object in the same memory location, and they are not potentially concurrent, the behavior is undefined

Unfortunately this means the behaviour of ++i + a[++i] is still undefined, because the left operand of + modifies i, and the right operand of + modifies i, and those operand evaluations are unsequenced relative to each other.


It has previously been proposed to make + and similar operators be left-right sequenced as well, but apparently this hasn't been accepted into the Standard yet.

M.M
  • 138,810
  • 21
  • 208
  • 365