cout, operator<<, sequence points

K

kalki70

Hello,

I have a doubt about this operator, and I haven't found the answer in
internet (yet).
When calling the operator << several times in an expression, are all
parameters evaluated first and then passed to cout::<<, or are being
passed when they are evaluated ?
An example to clarify my question :

int foo()
{
cout << "calling foo";
return 1;
}

......
cout << "i = " << foo() << endl;

Should I see this:

calling fooi = 1

or

i = calling foo1 ??

Or is it undefined behaviour?

So going to the original question.... is "i=" passed to cout::<< first
and then foo() is evaluated and passed to cout::<<, or is foo()
evaluated and just then "i = " and foo() are passed to cout::<< ?? Or
undefined behaviour?

Thanks in advance,

Luis
 
V

Victor Bazarov

kalki70 said:
I have a doubt about this operator, and I haven't found the answer in
internet (yet).
When calling the operator << several times in an expression, are all
parameters evaluated first and then passed to cout::<<, or are being
passed when they are evaluated ? [...]

The order of argument evaluation is _unspecified_ in the Standard.

Even if you figure it out (by introducing side effects, or looking
at the assembly), you should immediately forget about it because
the order may (and most likely will) be different with a different
compiler, different optimization setting of the same compiler or
just because it's a holiday.

V
 
K

kalki70

kalki70 said:
I have a doubt about this operator, and I haven't found the answer in
internet (yet).
When calling the operator << several times in an expression, are all
parameters evaluated first and then passed to cout::<<, or are being
passed when they are evaluated ? [...]

The order of argument evaluation is _unspecified_ in the Standard.

Even if you figure it out (by introducing side effects, or looking
at the assembly), you should immediately forget about it because
the order may (and most likely will) be different with a different
compiler, different optimization setting of the same compiler or
just because it's a holiday.

V


Yes, but this situation is more complicated and it is not clear to me.
It is very clear when I call a function with several parameters, like
func(f(x), g(x));
The order of evaluation of f(x) and g(x) is unspecified when calling
func().
But what happens when I can cout::<< several times like in my example?

cout << "i = " << foo() << endl;

Aren't these calls, 3 different independent calls to operator
cout::<< , every one with only one parameter?? And if they are 3
independent calls, is every parameter evaluated before calling
cout::<< each time, or are all parameters evaluated first, and then
all 3 calls to cout::<< are executed? How does this operator work?

It is this sintax, calling the same operator several times in one
expression which confuses me.

Thanks again,

Luis
 
V

Victor Bazarov

kalki70 said:
kalki70 said:
I have a doubt about this operator, and I haven't found the answer
in internet (yet).
When calling the operator << several times in an expression, are all
parameters evaluated first and then passed to cout::<<, or are being
passed when they are evaluated ? [...]

The order of argument evaluation is _unspecified_ in the Standard.

Even if you figure it out (by introducing side effects, or looking
at the assembly), you should immediately forget about it because
the order may (and most likely will) be different with a different
compiler, different optimization setting of the same compiler or
just because it's a holiday.

V


Yes, but this situation is more complicated and it is not clear to me.
It is very clear when I call a function with several parameters, like
func(f(x), g(x));
The order of evaluation of f(x) and g(x) is unspecified when calling
func().
But what happens when I can cout::<< several times like in my example?

cout << "i = " << foo() << endl;

Aren't these calls, 3 different independent calls to operator
cout::<< , every one with only one parameter??

No, it's three calls to different functions (all 'operator<<'), and
each of them has _two_ arguments (it's after all a _binary_ operator).
And if they are 3
independent calls, is every parameter evaluated before calling
cout::<< each time, or are all parameters evaluated first, and then
all 3 calls to cout::<< are executed? How does this operator work?

It is this sintax, calling the same operator several times in one
expression which confuses me.

Don't worry. It confuses many, not just you. The expression is
semantically equivalent to

operator << (operator << (operator << (cout, "i = "), foo()), endl)
^^^^^^^^^^^^^^^^^^^^^^^^^^ #1
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #2
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #3

As you can see there are _at_least_ four arguments here that need
to be evaluated before anything can proceed ('cout', '"i = "', 'foo()'
and 'endl'). The order of their evaluation is what I am talking about
-- it's unspecified. That means that the call to 'foo' can happen at
any point before the return value of it needs to be passed to the
operator<< call number 2. We know only one thing: the order of the
calls to the operator<< happens according to the numbers I showed here.

The order can be

endl
foo()
"i = " // nothing really needs to be evaluated
cout // nothing really needs to be evaluated
operator << #1
operator << #2
operator << #2

Or it can be

cout // nothing really needs to be evaluated
"i = " // nothing really needs to be evaluated
operator << #1
foo()
operator << #2
endl
operator << #2

Or it can be any other combination of things (with some specifics,
like a call to foo() can never happen after 'operator << #2').

There is nothing in the Standard that would make one more likely than
another.

Anything else is guesswork.

V
 
J

Jack Klein

kalki70 said:
I have a doubt about this operator, and I haven't found the answer in
internet (yet).
When calling the operator << several times in an expression, are all
parameters evaluated first and then passed to cout::<<, or are being
passed when they are evaluated ? [...]

The order of argument evaluation is _unspecified_ in the Standard.

Even if you figure it out (by introducing side effects, or looking
at the assembly), you should immediately forget about it because
the order may (and most likely will) be different with a different
compiler, different optimization setting of the same compiler or
just because it's a holiday.

V


Yes, but this situation is more complicated and it is not clear to me.
It is very clear when I call a function with several parameters, like
func(f(x), g(x));
The order of evaluation of f(x) and g(x) is unspecified when calling
func().
But what happens when I can cout::<< several times like in my example?

cout << "i = " << foo() << endl;

Aren't these calls, 3 different independent calls to operator
cout::<< , every one with only one parameter?? And if they are 3
independent calls, is every parameter evaluated before calling
cout::<< each time, or are all parameters evaluated first, and then
all 3 calls to cout::<< are executed? How does this operator work?

No, these are three calls to cout::eek:perator <<, each of which actually
has two arguments, the first of which is the implicit reference to a
stream. Furthermore, each call to cout::eek:perator << returns a
reference to an output stream, which happens to be exactly the same
reference that it was called with.

That is the reason that you can chain stream insertion and deletion
operators.

The second << (for foo() ) is called on the stream object reference
returned by the first << (for "i = " ). The third << (for endl) is
called on the stream object reference returned by the second << (for
foo() ).

This ensures that the calls to cout::eek:perator << are made in the order
written left-to-right, because each one needs the reference returned
by the one to its left.
It is this sintax, calling the same operator several times in one
expression which confuses me.

The order of calls to the insertion operator is fixed. The order of
evaluation of the operands is not. The compiler might generate code
to call foo() and store the result somewhere before it calls
cout::eek:perator << for the string literal. But it must make that
insertion call before it makes the insertion call for the value
returned by foo().

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html
 
K

kalki70

Victor, Jack, I really appreciate your answers, now it is also clear
to me.

Thanks a lot,

Luis
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top