Called a function with "cout" statement inside a "cout" statement
Asked Answered
H

3

19

I came across this rather vague behavior when messing around with code , here's the example :

#include <iostream>

using namespace std;


int print(void);

int main(void)
{
    cout << "The Lucky " << print() << endl;     //This line
    return 0;
}

int print(void)
{
    cout << "No : ";
    return 3;
}

In my code, the statement with comment //This lineis supposed to print out The Lucky No : 3, but instead it was printed No : The Lucky 3. What causes this behavior? Does this have to do with C++ standard or its behavior vary from one compiler to another?

Helaina answered 22/7, 2012 at 20:52 Comment(2)
Why do you believe that your expectation instead of the actual outcome is the more logical one? Can you explain your reasoning?Eneidaenema
Sidenote: Your print function is a nice example of a function with side-effects. Besides calculating a return value, it also changes global program state. Such functions are usually more difficult to reason about. Generally, strive towards functions that either compute a value or change state, but not both simultaneously.Eneidaenema
E
18

The order of evaluation of arguments to a function is unspecified. Your line looks like this to the compiler:

operator<<(operator<<(operator<<(cout, "The Lucky "), print()), endl);

The primary call in the statement is the one with endl as an argument. It is unspecified whether the second argument, endl, is evaluated first or the larger sub-expression:

operator<<(operator<<(cout, "The Lucky "), print())

And breaking that one down, it is unspecified whether the function print() is called first, or the sub-expression:

operator<<(cout, "The Lucky ")

So, to answer your question:

What causes this behavior? Does this has to do with C++ standard or its behavior vary from one compiler to another?

It could vary from compiler to compiler.

Execrate answered 22/7, 2012 at 21:1 Comment(7)
That's totally possible, and I might begin to see it ;)Plum
@atamanroman: In the following expression: operator<<(operator<<(cout, "The Lucky "), print()) What do you think should happen first, This: operator<<(cout, "The Lucky "), or this: print()? Justify your answer.Execrate
I know, It's not defined and I get it know. So cout << "The lucky " + print() would be well defined? Deleted my answer (+1).Plum
@atamanroman: Just for the sake of preciseness, you might want to be aware that there's a difference between "undefined" and "unspecified" behaviour. Roughly speaking, undefined behaviour means that anything can happen; unspecified behaviour means that what happens depends on the implementation (but implementations are not required to document what they do).Thaumatrope
@atamanroman: the behavior isn't undefined, it's unspecified -- there's a difference. The compiler is free to evaluate the parameters in whatever order (including a random order) that it finds best, it's not free to not evaluate a parameter at all or to blow up your toaster.Chanel
@atamanroman: cout << "The lucky" + print() would output No : lucky.Perpetuity
@BenjaminLindley Can you please also explain how the statments translated to 'operator<<(operator<<(operator<<(cout, "The Lucky "), print()), endl); 'Expressman
D
4

Let's call the operator << simply operator .

Now we can write

cout << "The Lucky"

as

operator(cout, "The Lucky")

The result of this operation is cout, and it is passed to next <<, so we can write

operator(operator(cout, "The Lucky"), print() )

It is a function invocation with two parameters, and the standard doesn't say anything about the order of their evaluation.

So with some compilers you really may get

The Lucky No : 3
Dancette answered 22/7, 2012 at 21:2 Comment(0)
B
0

In my compiler No: The Lucky 3 is the output.... it means that its behaviour varies from compiler to compiler.

Bedel answered 20/11, 2015 at 17:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.