Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c++

c++-faq

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

like image 993
pravs Avatar asked May 28 '12 10:05

pravs


People also ask

What is << in cout?

It is used to display the output to the standard output device i.e. monitor. It is associated with the standard C output stream stdout. The data needed to be displayed on the screen is inserted in the standard output stream (cout) using the insertion operator(<<).

What does << mean in C++?

MiiNiPaa (8886) << is a bitwise left shift operator. It is overloaded to work differently with ostream and derived classes. Standard library provides overloads fo all built-in types and several calsses from standard library (std::string for example). You can also provide overload for your own classes.

What does cout stand for in C++?

The "c" in cout refers to "character" and "out" means "output". Hence cout means "character output". The cout object is used along with the insertion operator << in order to display a stream of characters.

What is the output of below program int main (){ int a 10 cout << A ++; return 0 *?

Expert-verified answer From the instruction the output put of the program is 10.


2 Answers

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.

like image 197
Maxim Egorushkin Avatar answered Oct 30 '22 19:10

Maxim Egorushkin


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

like image 44
Alok Save Avatar answered Oct 30 '22 19:10

Alok Save