Re: What is the Output of this program?
The order of evaluation of arguments is not defined. The compiler is allowed to do the various increments in any order it wishes as long as the appropriate one is done at the time the relevant function is entered. It could, if it wants, evaluate all of the increments in any order before entering the first function in the chain. The output is still undefined.
I should also point out that your original recast into functions is wrong.
The expression translates as:
Code:
operator<<(
operator<<(
operator<<(
operator<<(
operator<<(
operator<<(
operator<<(
cout, var1
)," "
), var1++
), " "
), ++var1
), " "
), var1++
);
So you can see that it is entirely possible for the compiler to plant the increments in any order it wishes prior to entering the first function call (and, therefore, sequence point).
THE OUTPUT IS UNDEFINED.
Re: What is the Output of this program?
Quote:
Originally Posted by SuperKoko
Is a sequence of function calls, with only one (or zero) side effect at each function call.
This stuff is pretty new to me too, but I believe the fact that they're nested function calls, rather than sequential ones, is what causes the problem. As a general example, consider an expression of the form:
Code:
Fn1( Fn2( Ex1, Ex2 ), Ex3 );
Here we have two function calls Fn1 and Fn2, and three expressions Ex1 through Ex3. Those expressions may well be something of the form var1++ as in the original example.
First we encounter a call to Fn1(). Before calling the function, its arguments must be evaluated. It is not defined which will be evaluated first: either the expression Ex3, or the call to Fn2(). Eventually Fn2() will be evaluated, but before it is, its own arguments must be evaluated. And again, it is not defined which will occur first: the evaluation of Ex1 or Ex2. In this way, only once all three expressions have been evaluated is the first function call made, and thus a sequence point encountered. It is conceivable that Ex1, Ex2, and Ex3 will be evaluated in any possible order.
If you want to confirm for yourself that this is indeed what's happening, compile the program from the original post and look at the assembly code the compiler generates. Here's what I got from VC++ 6.0 with optimizations off:
Code:
7: cout << var1 << " " << var1++ << " " << ++var1 << " " << var1++;
0040178F mov eax,dword ptr [ebp-4]
00401792 mov dword ptr [ebp-8],eax
00401795 mov ecx,dword ptr [ebp-8]
00401798 push ecx
00401799 mov edx,dword ptr [ebp-4]
0040179C add edx,1
0040179F mov dword ptr [ebp-4],edx
004017A2 push offset string " " (0046b01c)
004017A7 mov eax,dword ptr [ebp-4]
004017AA add eax,1
004017AD mov dword ptr [ebp-4],eax
004017B0 mov ecx,dword ptr [ebp-4]
004017B3 push ecx
004017B4 push offset string " " (0046b01c)
004017B9 mov edx,dword ptr [ebp-4]
004017BC mov dword ptr [ebp-0Ch],edx
004017BF mov eax,dword ptr [ebp-0Ch]
004017C2 push eax
004017C3 mov ecx,dword ptr [ebp-4]
004017C6 add ecx,1
004017C9 mov dword ptr [ebp-4],ecx
004017CC push offset string " " (0046b01c)
004017D1 mov edx,dword ptr [ebp-4]
004017D4 push edx
004017D5 mov ecx,offset std::cout (004767e0)
004017DA call @ILT+245(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004010fa)
004017DF push eax
004017E0 call @ILT+625(std::operator<<) (00401276)
004017E5 add esp,8
004017E8 mov ecx,eax
004017EA call @ILT+245(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004010fa)
004017EF push eax
004017F0 call @ILT+625(std::operator<<) (00401276)
004017F5 add esp,8
004017F8 mov ecx,eax
004017FA call @ILT+245(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004010fa)
004017FF push eax
00401800 call @ILT+625(std::operator<<) (00401276)
00401805 add esp,8
00401808 mov ecx,eax
0040180A call @ILT+245(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004010fa)
As you can see here, by the time any calls are made, the increments have all been performed, and all seven output characters (the four values plus pointers to three string literals) have been pushed onto the stack. So, if I understood the article right, there would have been no sequence points encountered at any time between the beginning of this line's evaluation and the time when all the arguments for all the function calls have been evaluated.
Re: What is the Output of this program?
Thank you for that explanation. Very clear. :thumb:
Re: What is the Output of this program?
I was thinking about this while trying to go to sleep and realized that I think I made an error in my last post, so here's a probably useless question/clarification:
Quote:
Originally Posted by Smasher/Devourer
It is conceivable that Ex1, Ex2, and Ex3 will be evaluated in any possible order.
Now that I think about it, in the example I gave, I think that Fn2() would be called once both Ex1 and Ex2 have been evaluated, meaning that several permutations still exist, but it's impossible or at least extremely unlikely for Ex3 to be evaluated between Ex1 and Ex2. That is, you could expect any of these four cases:
Ex3
Ex1
Ex2
Fn2()
Fn1()
Ex3
Ex2
Ex1
Fn2()
Fn1()
Ex1
Ex2
Fn2()
Ex3
Fn1()
Ex2
Ex1
Fn2()
Ex3
Fn1()
But for Ex3 to be evaluated before Ex1 and after Ex2 doesn't seem likely. That would mean that in evaluating the arguments to Fn1() -- that is, Fn2(Ex1, Ex2) and Ex3 -- the program would have to start evaluating the first argument, then stop halfway through and evaluate the second, before completing its evaluation of the first. Is that right? Does the standard forbid something like this? Even if it doesn't, I sincerely doubt that a compiler would ever evaluate arguments in such a strange way. Anyone have a thought on this? Am I just spouting nonsense because I'm up too late?
In any case, I think the general spirit of my last post still stands, even if it's a bit rough around the edges. ;)
Re: What is the Output of this program?
Thanks Smasher/Devourer for your very good posts.
And, yes of course there are nested function calls, and primarly i was thinking that because each function call depends of the previous and there is a sequence point between two function calls the result was defined... But that is false because parameter evaluation can be in any order, so finally the result is undefined.
You made all clear in my mind.
Thanks.
Re: What is the Output of this program?
Quote:
Originally Posted by Smasher/Devourer
the program would have to start evaluating the first argument, then stop halfway through and evaluate the second, before completing its evaluation of the first. Is that right? Does the standard forbid something like this?
I really think that the standard allows that, even if very few compilers will do it.
Because all side effects must be done before the function is called, but the funcion can be called after Ex3 has been evaluated (you know that well). And between two sequence points all side effects can occur in any order, really any order.
Re: What is the Output of this program?
this Output is undfefined
totally depend on compiler behaviour
if u run same program on turbo C,Visual C,or gcc
each one is going to gave different output
depend how compiler treat them
Better to follow gcc logic
if two compiler follows all ANSI rule only then you can get same output
Re: What is the Output of this program?
I know this topic has been beaten to death, but I was just reviewing my copy of "The C++ Standard Library" and Josuttis says the following with respect to a line with a long chain of stream outputs:
Quote:
"Thus,
is executed first. Note that the evaluative order of the operator does not imply any specific order in which the arguments are evaluated; only the order in which the
operators are executed is defined.