What is the correct answer for cout << a++ << a;?

Recently in an interview there was a following objective type question.

int a = 0;
cout << a++ << a;

Answers:

a. 10
b. 01
c. undefined behavior

I answered choice b, i.e. output would be "01".

But to my surprise later I was told by an interviewer that the correct answer is option c: undefined.

Now, I do know the concept of sequence points in C++. The behavior is undefined for the following statement:

int i = 0;
i += i++ + i++;

but as per my understanding for the statement cout << a++ << a , the ostream.operator<<() would be called twice, first with ostream.operator<<(a++) and later ostream.operator<<(a).

I also checked the result on VS2010 compiler and its output is also '01'.


Solution 1:

You can think of:

cout << a++ << a;

As:

std::operator<<(std::operator<<(std::cout, a++), a);

C++ guarantees that all side effects of previous evaluations will have been performed at sequence points. There are no sequence points in between function arguments evaluation which means that argument a can be evaluated before argument std::operator<<(std::cout, a++) or after. So the result of the above is undefined.


C++17 update

In C++17 the rules have been updated. In particular:

In a shift operator expression E1<<E2 and E1>>E2, every value computation and side-effect of E1 is sequenced before every value computation and side effect of E2.

Which means that it requires the code to produce result b, which outputs 01.

See P0145R3 Refining Expression Evaluation Order for Idiomatic C++ for more details.

Solution 2:

Technically, overall this is Undefined Behavior.

But, there are two important aspects to the answer.

The code statement:

std::cout << a++ << a;

is evaluated as:

std::operator<<(std::operator<<(std::cout, a++), a);

The standard does not define the order of evaluation of arguments to an function.
So Either:

  • std::operator<<(std::cout, a++) is evaluated first or
  • ais evaluated first or
  • it might be any implementation defined order.

This order is Unspecified[Ref 1] as per the standard.

[Ref 1]C++03 5.2.2 Function call
Para 8

The order of evaluation of arguments is unspecified. All side effects of argument expression evaluations take effect before the function is entered. The order of evaluation of the postfix expression and the argument expression list is unspecified.

Further, there is no sequence point between evaluation of arguments to a function but a sequence point exists only after evaluation of all arguments[Ref 2].

[Ref 2]C++03 1.9 Program execution [intro.execution]:
Para 17:

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.

Note that, here the value of c is being accessed more than once without an intervening sequence point, regarding this the standard says:

[Ref 3]C++03 5 Expressions [expr]:
Para 4:

....
Between the previous and next sequence point a scalar object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be accessed only to determine the value to be stored. The requirements of this paragraph shall be met for each allowable ordering of the subexpressions of a full expression; otherwise the behavior is undefined.

The code modifies c more than once without intervening sequence point and it is not being accessed to determine the value of the stored object. This is clear violation of the above clause and hence the result as mandated by the standard is Undefined Behavior[Ref 3].