Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Output order for cout << "Hello, " << "world!" ?

2 views
Skip to first unread message

Timothy Madden

unread,
Aug 19, 2010, 3:15:40 PM8/19/10
to
Hello

Is it true that the language does not actually guarantee the output
order for

cout << "Hello, " << "world.!" << endl;

like it could possibly output "world !\nHello" or the like ?

Because there is no semicolon ";" to introduce a sequence point, until
the end of the expression, and until then, the order of all side-effects
unspecified ?

I have tried to understand this and it occur to me that the above
expression is really a function-call expression, and should follow the
semantics of a function call, like

operator <<
(
operator <<(operator <<(cout, "Hello, "), "world !"),
endl
);

and a function call is also a sequence point, like ";" is. So in the end
I see the output order is guranteed. Unless standard library functions
are somehow different than third-party libraries functions. So why would
they say that there is no order when chaining output operators like this ?

Thank you,
Timothy Madden

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Daniel Krügler

unread,
Aug 19, 2010, 10:36:32 PM8/19/10
to
On 19 Aug., 21:15, Timothy Madden <terminato...@gmail.com> wrote:
> Hello
>
> Is it true that the language does not actually guarantee the output
> order for
>
> cout << "Hello, " << "world.!" << endl;
>
> like it could possibly output "world !\nHello" or the like ?
>
> Because there is no semicolon ";" to introduce a sequence point, until
> the end of the expression, and until then, the order of all side-effects
> unspecified ?

You are mixing something up here. The language says that
the *evaluation* order of the function arguments is
unspecified, but it doesn't say that a compiler may
change a function call f(g()) to g(f()).

> I have tried to understand this and it occur to me that the above
> expression is really a function-call expression, and should follow the
> semantics of a function call, like
>
> operator <<
> (
> operator <<(operator <<(cout, "Hello, "), "world !"),
> endl
> );
>
> and a function call is also a sequence point, like ";" is. So in the end
> I see the output order is guranteed.

The order of output is guaranteed, otherwise no-one
would seriously use the IO stream inserters.

> Unless standard library functions
> are somehow different than third-party libraries functions. So why would
> they say that there is no order when chaining output operators like this ?

The difference is in the meaning of "order of
argument evaluation" (1.9/15).

HTH & Greetings from Bremen,

Daniel Krügler

Bo Persson

unread,
Aug 19, 2010, 10:37:13 PM8/19/10
to
Timothy Madden wrote:
> Hello
>
> Is it true that the language does not actually guarantee the output
> order for
>
> cout << "Hello, " << "world.!" << endl;
>
> like it could possibly output "world !\nHello" or the like ?
>
> Because there is no semicolon ";" to introduce a sequence point,
> until the end of the expression, and until then, the order of all
> side-effects unspecified ?
>
> I have tried to understand this and it occur to me that the above
> expression is really a function-call expression, and should follow
> the semantics of a function call, like
>
> operator <<
> (
> operator <<(operator <<(cout, "Hello, "), "world !"),
> endl
> );
>
> and a function call is also a sequence point, like ";" is. So in
> the end I see the output order is guranteed. Unless standard
> library functions are somehow different than third-party libraries
> functions. So why would they say that there is no order when
> chaining output operators like this ?

The order of the output is very well defined. What isn't defined is
the order of evaluation of the parameters of the different functions,
but as long as these have no visible side effects it doesn't matter.

Library functions are just functions, there is no magic(*). That's the
beauty of C++ - we can all write libraries using the language
features, not just the compiler writer.


Bo Persson

(*) with a very few exceptions, where the standard library might have
to use implementation specific features, like how to initialize
iostreams before main().

red floyd

unread,
Aug 19, 2010, 10:36:43 PM8/19/10
to
On Aug 19, 12:15 pm, Timothy Madden <terminato...@gmail.com> wrote:
> Hello
>
> Is it true that the language does not actually guarantee the output
> order for
>
> cout << "Hello, " << "world.!" << endl;
>
> like it could possibly output "world !\nHello" or the like ?
>
> Because there is no semicolon ";" to introduce a sequence point, until
> the end of the expression, and until then, the order of all side-effects
> unspecified ?
>
> I have tried to understand this and it occur to me that the above
> expression is really a function-call expression, and should follow the
> semantics of a function call, like
>
> operator <<
> (
> operator <<(operator <<(cout, "Hello, "), "world !"),
> endl
> );
>

No, the output order is guaranteed. What is not guaranteed is the
order of the evaluation of the OPERANDS.

That is,

cout << expr1 << expr2 << endl;

The order of evaluation of expr1 and expr2 is not guaranteed.

hak...@gmail.com

unread,
Aug 19, 2010, 10:41:31 PM8/19/10
to
On Aug 19, 3:15 pm, Timothy Madden <terminato...@gmail.com> wrote:
> Hello
>
> Is it true that the language does not actually guarantee the output
> order for
>
> cout << "Hello, " << "world.!" << endl;

There is at least one situation where you're right, the order is not
guaranteed.

// Psuedocode:
void f()
{
cout << "Hello, " << "world.!" << endl;
}

int main()
{
thread t1(f), t2(f);
t1.join(); t2.join();
}

The output there could, theoretically, be
"Hello, Hello, world.!world.!

"
I don't know that there are any other situations where this wouldn't
output as expected though.

Joshua Maurice

unread,
Aug 20, 2010, 5:14:32 PM8/20/10
to
On Aug 19, 12:15 pm, Timothy Madden <terminato...@gmail.com> wrote:
> Hello
>
> Is it true that the language does not actually guarantee the output
> order for
>
> cout << "Hello, " << "world.!" << endl;
>
> like it could possibly output "world !\nHello" or the like ?
>
> Because there is no semicolon ";" to introduce a sequence point, until
> the end of the expression, and until then, the order of all side-effects
> unspecified ?
>
> I have tried to understand this and it occur to me that the above
> expression is really a function-call expression, and should follow the
> semantics of a function call, like
>
> operator <<
> (
> operator <<(operator <<(cout, "Hello, "), "world !"),
> endl
> );
>
> and a function call is also a sequence point, like ";" is. So in the end
> I see the output order is guranteed. Unless standard library functions
> are somehow different than third-party libraries functions. So why would
> they say that there is no order when chaining output operators like this ?

To add to the already existing numerous correct replies, here's my
take. In short, you have several misconceptions. Hopefully the
following examples will make it clear.

Let's take the horrible code: (1)
#include <iostream>
int x = 0;
int foo() { return ++x; }
int main()
{
std::cout << foo() << foo() << foo() << std::endl;
}
This is exactly equivalent to: (2)
#include <iostream>
int x = 0;
int foo() { return ++x; }
int main()
{
std::cout.operator<< (foo()).operator<< (foo()).operator<<
(foo()).operator<< (std::endl);
}
'operator <<' is a name of a function. 'operator <<' is a name with
special meaning in C++. Defining the function 'operator <<' allows a
user to use the inplace 'cout << foo' syntax, whereas defining a
function named 'print' would not give the user any special function
call syntax. If you were to write the standard ostream class
differently, you could give the function a different name, like
'print': (3)
#include <iostream>
int x = 0;
int foo() { return ++x; }
int main()
{
std::cout.print(foo()).print(foo()).print(foo()).print(std::endl);
}
This is almost equivalent to the following, but there is a big and
important difference: (4)
#include <iostream>
int x = 0;
int foo() { return ++x; }
int main()
{
std::ostream& tmp1 = std::cout.operator<< (foo());
std::ostream& tmp2 = tmp1.operator<< (foo());
std::ostream& tmp3 = tmp2.operator<< (foo());
std::ostream& tmp4 = tmp3.operator<< (std::endl);
}
In examples 1, 2, and 3, there are multiple expressions as arguments
to functions in a single statement, including the three calls to
function foo. In this situation, the order of evaluation of the three
function foo calls is unspecified. It could print:
123
or
231
or any of the 6 total combinations. The result of "first foo function
call by source code" will be put to stdout first, but the "first foo
function call by source code" may be the first, second, or third foo
evaluated, resulting in a different return value. (A conforming
implementation could even change the order between executions, or even
change the order in the same execution if the code is executed
multiple times, such as in a loop.) When the print member function
calls are put in separate statements, like example 4, then the order
of evaluation of the function foo calls is defined, and it will
print:
123

Seungbeom Kim

unread,
Aug 21, 2010, 12:05:19 PM8/21/10
to
On 2010-08-19 12:15, Timothy Madden wrote:
> Hello
>
> Is it true that the language does not actually guarantee the output
> order for
>
> cout << "Hello, " << "world.!" << endl;
>
> like it could possibly output "world !\nHello" or the like ?
>
> Because there is no semicolon ";" to introduce a sequence point, until
> the end of the expression, and until then, the order of all side-effects
> unspecified ?
>
> I have tried to understand this and it occur to me that the above
> expression is really a function-call expression, and should follow the
> semantics of a function call, like
>
> operator <<
> (
> operator <<(operator <<(cout, "Hello, "), "world !"),
> endl
> );
>
> and a function call is also a sequence point, like ";" is. So in the end
> I see the output order is guranteed. Unless standard library functions
> are somehow different than third-party libraries functions. So why would
> they say that there is no order when chaining output operators like this ?

It's not about sequence points, but it's about the associativity of the
operators.

f() + g() + h()

In this example, it is unspecified in which order f(), g(), and h() will
be called and evaluated, but the whole expression is always evaluated as

(f() + g()) + h()

that is, the addition of f() and g() is performed first and h() is added
to the result, and it's never evaluated as

f() + (g() + h())

because the associativity of + is left-to-right. On the other hand,

x = y = z

is always evaluated as

x = (y = z)

because the associativity of = is right-to-left.

Similarly, in the case of stream insertion,

cout << f() << g()

is always evaluated as

(cout << f()) << g()

because the associativity of << is left-to-right. While it is unspecified
that which of f() or g() will be called and evaluated first, but there's
no way that the result of g() can be printed before the subexpression
(cout << f()) is evaluated and its result (which happens to be just cout)
is calculated. Therefore the output order is guaranteed to be left-to-right.

The evaluation order can be anything that is a topological ordering of
the following graph:

f() --> <<(1st) \
-> <<(2nd)
g() ------------/

i.e.

f() --> <<(1st) --> g() --> <<(2nd)
f() --> g() --> <<(1st) --> <<(2nd)
g() --> f() --> <<(1st) --> <<(2nd)


* Note: The standard doesn't actually define "associativity" for the
operators, but it's implicit from the syntax that it defines, and
nevertheless a useful concept.

--
Seungbeom Kim

0 new messages