Home > Back-end >  Is std::cin >> i >> i; undefined behavior
Is std::cin >> i >> i; undefined behavior

Time:12-28

I am trying to understand the order of evaluation of expressions in C . I have the following examples:

int i = 0;
std::cin >> i >> i; //IS THIS UB? 

My first question is that does the above shown snippet produces UB?

Next,

int i = 0;
std::cin >> i >>   i; //IS THIS UB?

My second question is that does this snippet produces UB?

CodePudding user response:

std::cin >> i >> i; is and always was well-defined.

std::cin >> i >> i; is well-defined now, but was UB pre-C 17.

This kind of UB is caused either by unsequenced writes to the same scalar, or a write unsequenced relative to a read of the same scalar.

In std::cin >> i >> i;, even though i is modified twice (inside of the overloaded >>), the first modification is sequenced before the second one. The return value of the first >> has to be calculated first, to be passed as an argument to the second >>, so they have to be called in this order. See rule (3) here.

In std::cin >> i >> i;, on the other hand, pre-C 17 the modification of i by the first >> was unsequenced relative to i, causing UB. But in C 17 and newer, >> and << always evaluate the lhs before rhs, causing the first >> to be sequenced before i, see rule (19) here.

CodePudding user response:

Case I

In this case, std::cin >> i >> i; can be written as(or equivalent to):

std::cin.operator>>(i).operator>>(i);

There are 2 important things to consider here

  1. std::cin::operator>> returns cin object by reference
  2. Each call to std::cin>>operator>> is guaranteed to be made in order from left to right.

So there is no undefined behavior in this case.

Case II

In this case, std::cin >> i >> i; can be written as(or equivalent to):

std::cin.operator>>(i).operator>>(  i);

Now, from Section 1.9, Point 16:

When calling a function (whether or not the function is inline), there is a sequence point after the evaluation of all function arguments (if any) which takes place before execution of any expressions or statements in the function body. There is also a sequence point after the copying of a returned value and before the execution of any expressions outside the function.

But note that the above quote statement only guarantees that:

  1. i is evaluated before the first call to operator>> and
  2. i is evaluated before the second call to operator>>.

But the quote doesn't guarantee that i is evaluated before i or vice versa. This means that the order in which i and i are evaluated is undefined and so the resulting code in this case will have undefined behavior.

The above discussion(sequence points) is for Pre-C 11 since OP didn't tag C 11.

  • Related