Thread: [Dev-C++] Problem with 'std::cout' (?)
Open Source C & C++ IDE for Windows
Brought to you by:
claplace
|
From: Franco B. <fbr...@gm...> - 2007-10-04 14:15:17
|
Dear Friends,
I observed an irregular (I think) comportment of 'std::cout'
reproduced by the simple test code below:
#include <iostream>
using namespace std;
int myFunc(); // simple test function prototype
// test program
int main()
{
cout << myFunc() << endl // this block results
<< myFunc() << endl // in an inverted
<< myFunc() << endl << endl; // console output
cout << myFunc() << endl; // this block results
cout << myFunc() << endl; // in a correct
cout << myFunc() << endl << endl; // console output
system("PAUSE");
return 0;
}
// simple test function implementation
int myFunc()
{
static int i = 1024;
i /= 2;
return i;
}
The console output for this code is:
128
256
512
64
32
16
Press any key to continue...
The questions:
The two 'cout' blocks act in a different manner! (?)
Why the first chained block results in an inverted output?
Does not the insert operator '<<' act from left to right?
Obs.: I'm using
Dev-C++ 4.9.9.2,
Win XP 5.1,
g++ (1/29/2005).
TIA,
Franco Brancaccio
fbr...@gm...
|
|
From: matheus r. <mfr...@gm...> - 2007-10-04 14:43:00
|
The statement evaluation happens from right to the left, like all
others. But the ostream operator << acts like a stack. You evaluate
expression from right, push. Then at the end, everything added is
popped.
So basically, you push 512, 256, 128. Then you pop 128, 256, 512.
2007/10/4, Franco Brancaccio <fbr...@gm...>:
> Dear Friends,
>
> I observed an irregular (I think) comportment of 'std::cout'
> reproduced by the simple test code below:
>
>
> #include <iostream>
> using namespace std;
>
>
> int myFunc(); // simple test function prototype
>
>
> // test program
> int main()
> {
> cout << myFunc() << endl // this block results
> << myFunc() << endl // in an inverted
> << myFunc() << endl << endl; // console output
>
> cout << myFunc() << endl; // this block results
> cout << myFunc() << endl; // in a correct
> cout << myFunc() << endl << endl; // console output
>
> system("PAUSE");
> return 0;
> }
>
>
> // simple test function implementation
> int myFunc()
> {
> static int i = 1024;
> i /= 2;
> return i;
> }
>
>
> The console output for this code is:
>
>
> 128
> 256
> 512
>
> 64
> 32
> 16
>
> Press any key to continue...
>
>
> The questions:
> The two 'cout' blocks act in a different manner! (?)
> Why the first chained block results in an inverted output?
> Does not the insert operator '<<' act from left to right?
>
> Obs.: I'm using
> Dev-C++ 4.9.9.2 ,
> Win XP 5.1,
> g++ (1/29/2005).
>
>
> TIA,
> Franco Brancaccio
> fbr...@gm...
>
>
> -------------------------------------------------------------------------
> This SF.net email is sponsored by: Splunk Inc.
> Still grepping through log files to find problems? Stop.
> Now Search log events and configuration files using AJAX and a browser.
> Download your FREE copy of Splunk now >> http://get.splunk.com/
> _______________________________________________
> Dev-cpp-users mailing list
> Dev...@li...
> TO UNSUBSCRIBE:
> http://www23.brinkster.com/noicys/devcpp/ub.htm
> https://lists.sourceforge.net/lists/listinfo/dev-cpp-users
>
>
|
|
From: matheus r. <mfr...@gm...> - 2007-10-04 18:16:34
|
Ok, my bad here. Disregard my previous mail.
The operator << evaluation happens from left to right. But probably,
the compiler evaluates all parameters in the line first from right to
left, then applies operator <<.
Perhaps other people can help here, interesting question.
2007/10/4, matheus ribeiro <mfr...@gm...>:
> The statement evaluation happens from right to the left, like all
> others. But the ostream operator << acts like a stack. You evaluate
> expression from right, push. Then at the end, everything added is
> popped.
>
> So basically, you push 512, 256, 128. Then you pop 128, 256, 512.
>
> 2007/10/4, Franco Brancaccio <fbr...@gm...>:
> > Dear Friends,
> >
> > I observed an irregular (I think) comportment of 'std::cout'
> > reproduced by the simple test code below:
> >
> >
> > #include <iostream>
> > using namespace std;
> >
> >
> > int myFunc(); // simple test function prototype
> >
> >
> > // test program
> > int main()
> > {
> > cout << myFunc() << endl // this block results
> > << myFunc() << endl // in an inverted
> > << myFunc() << endl << endl; // console output
> >
> > cout << myFunc() << endl; // this block results
> > cout << myFunc() << endl; // in a correct
> > cout << myFunc() << endl << endl; // console output
> >
> > system("PAUSE");
> > return 0;
> > }
> >
> >
> > // simple test function implementation
> > int myFunc()
> > {
> > static int i = 1024;
> > i /= 2;
> > return i;
> > }
> >
> >
> > The console output for this code is:
> >
> >
> > 128
> > 256
> > 512
> >
> > 64
> > 32
> > 16
> >
> > Press any key to continue...
> >
> >
> > The questions:
> > The two 'cout' blocks act in a different manner! (?)
> > Why the first chained block results in an inverted output?
> > Does not the insert operator '<<' act from left to right?
> >
> > Obs.: I'm using
> > Dev-C++ 4.9.9.2 ,
> > Win XP 5.1,
> > g++ (1/29/2005).
> >
> >
> > TIA,
> > Franco Brancaccio
> > fbr...@gm...
> >
> >
> > -------------------------------------------------------------------------
> > This SF.net email is sponsored by: Splunk Inc.
> > Still grepping through log files to find problems? Stop.
> > Now Search log events and configuration files using AJAX and a browser.
> > Download your FREE copy of Splunk now >> http://get.splunk.com/
> > _______________________________________________
> > Dev-cpp-users mailing list
> > Dev...@li...
> > TO UNSUBSCRIBE:
> > http://www23.brinkster.com/noicys/devcpp/ub.htm
> > https://lists.sourceforge.net/lists/listinfo/dev-cpp-users
> >
> >
>
|
|
From: matheus r. <mfr...@gm...> - 2007-10-05 16:37:06
|
Elaborating a bit more on the problem. The C/C++ compiler is free to
evaluate function parameters in any order. In the case of gcc/g++,
function parameter evaluation happens from right to left. Also, all
parameters have to be evaluated before function call.
The function:
--- ostream &operator <<(ostream &, int)
acts just like:
--- ostream& write(ostream &s, int i){ s.write(i); return s; }
Thus, this statement:
--- cout << f1() << f2() << f3();
is equivalent to:
--- write3( write2( write1(cout, f1() ), f2() ), f3() );
because the << operator is evaluated from left to right. I renamed
functions to make it easier to explain (write1, write2, write3 are the
same, like f1, f2 and f3).
When compiler sees this, it:
1- evaluates write3 right parameter, f3r = f3().
2- evaluates write3 left parameter, write2( write1(cout, f1() ), f2() ).
2.1 - evaluates write2 right parameter, f2r = f2()
2.2- evaluates write2 left parameter write1(cout, f1() )
2.2.1- evaluates write1 right parameter, f1r = f1()
2.2.2- call w1r = write1(cout, f1r)
2.3- call w2r = write2(w1r, f2r)
3- call write3(w2r, f3r)
So, the f functions will be called in the order: f3(), f2(), f1()
before any of the write functions due to parameter order evaluation.
The write functions will happen in the order write1(), write2(),
write3().
As a result, the f functions will be called in reverse order, but the
stream will be written in correct the order. The side effect of the f
functions are responsible for the weird result you see. If a function
has a side effect on itselft, you can not rely on the order of
parameters if its called multiple times as parameters, since each
compiler is free to evaluate parameters in any order.
Sorry for bringing this up again, just wanted to clear it up.
|
|
From: Franco B. <fbr...@gm...> - 2007-10-05 17:16:28
|
OK.
I 'supposed' it was an intrinsic compiler feature.
But nothing better than a detailed explanation given by an expert!
I guess, the better strategy is to use 'separate-cout' statements in similar
situations.
Thanks,
Franco
2007/10/5, matheus ribeiro <mfr...@gm...>:
>
> Elaborating a bit more on the problem. The C/C++ compiler is free to
> evaluate function parameters in any order. In the case of gcc/g++,
> function parameter evaluation happens from right to left. Also, all
> parameters have to be evaluated before function call.
>
> The function:
>
> --- ostream &operator <<(ostream &, int)
>
> acts just like:
>
> --- ostream& write(ostream &s, int i){ s.write(i); return s; }
>
> Thus, this statement:
>
> --- cout << f1() << f2() << f3();
>
> is equivalent to:
>
> --- write3( write2( write1(cout, f1() ), f2() ), f3() );
>
> because the << operator is evaluated from left to right. I renamed
> functions to make it easier to explain (write1, write2, write3 are the
> same, like f1, f2 and f3).
>
> When compiler sees this, it:
> 1- evaluates write3 right parameter, f3r = f3().
> 2- evaluates write3 left parameter, write2( write1(cout, f1() ), f2() ).
> 2.1 - evaluates write2 right parameter, f2r = f2()
> 2.2- evaluates write2 left parameter write1(cout, f1() )
> 2.2.1- evaluates write1 right parameter, f1r = f1()
> 2.2.2- call w1r = write1(cout, f1r)
> 2.3- call w2r = write2(w1r, f2r)
> 3- call write3(w2r, f3r)
>
> So, the f functions will be called in the order: f3(), f2(), f1()
> before any of the write functions due to parameter order evaluation.
> The write functions will happen in the order write1(), write2(),
> write3().
>
> As a result, the f functions will be called in reverse order, but the
> stream will be written in correct the order. The side effect of the f
> functions are responsible for the weird result you see. If a function
> has a side effect on itself, you can not rely on the order of
> parameters if its called multiple times as parameters, since each
> compiler is free to evaluate parameters in any order.
>
> Sorry for bringing this up again, just wanted to clear it up.
>
|