Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Behaviour of arr[i] = i++ and i = i + 1 statements in C and C++

In the C and C++ languages, the arr[i] = i++; statement invokes undefined behavior. Why does the statement i = i + 1; not invoke undefined behavior?

like image 962
Jayesh Avatar asked Jun 03 '17 06:06

Jayesh


3 Answers

Since this was originally tagged with c and c++ and not any specific version(s), the below answer is a generic answer to the problem. However, please note for c++, C++17 onwards, the behaviour has changed. Please see this answer by Barry to know more.


For the statement

arr[i] = i++;

the value of i is used in both the operands, RHS(right-hand-side) and LHS(left-hand-side), and in one of the cases, the value is being modified (as a side effect of post ++) where there's no sequence point in between to determine which value of i should be considered. You can also check this canonical answer for more on this.

On the other hand, for i = i + 1, the value of i is used only in RHS, the computed result is stored in LHS, in other words, there's no ambiguity. We can write the same statement as i++, which

  • reads the value of i
  • Increments it by 1
  • stores it back to i

in a well-defined sequence. Hence, no issues.

like image 192
Sourav Ghosh Avatar answered Nov 14 '22 04:11

Sourav Ghosh


Note that this will change in C++17. In C++17, arr[i] = i++ does not invoke undefined behavior. This is due to the following change in [expr.ass]:

In all cases, the assignment is sequenced after the value computation of the right and left operands, and before the value computation of the assignment expression. The right operand is sequenced before the left operand.

That is, we do i++ then we do arr[i] then we perform the assignment. The now well-defined ordering is:

auto src = i++;
auto& dst = arr[i];
dst = src;
like image 29
Barry Avatar answered Nov 14 '22 02:11

Barry


For C99, we have:

6.5 Expressions

  1. 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.

In arr[i] = i++, the value of i is only modified once. But arr[i] also reads from i, and this value is not used to determine the new value of i. That's why it has undefined behavior.

On the other hand, in i = i + 1 we read i in order to compute i + 1, which is used as the new value of i. Therefore this expression is fine.

like image 9
melpomene Avatar answered Nov 14 '22 03:11

melpomene