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
std::cin::operator>>
returnscin
object by reference- 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:
i
is evaluated before the first call tooperator>>
andi
is evaluated before the second call tooperator>>
.
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.