Possible Duplicate:
Compilers and argument order of evaluation in C++ cout << order of call to functions it prints?
This:
int k=3; printf("%d %d %d",k++,k,++k);
Gives output as
4 4 4
because they are pushed into the stack as:%d%d%d 4 -- for k++ 4 --for k 4 --for ++k
Right?
This:
int k = 3; cout << k++ << k << ++k;
Is actually repeated function calls, so it's equivalent to:
( ( (cout << k++) << k) << ++k);
So, I suppose first of all
k++
thenk
and then++k
must always be executed in this order, right? I believe a function 开发者_JAVA技巧call is a sequence point, but the outputs vary on different implementations. Why is this so?
The order of evaluation of arguments is unspecified by the standards. That means, it can happen in any order the implementation wants to.
This is undefined because there is no sequence point between the , in the printf statement. Without a sequence point the compiler is free to order writes to the memory location k
as it wills.
Now you may be wondering 'what the hell is a seqeunce point' and why is it relevant? Basically a sequence point is a point in the code where the memory location in question, in this case k
has been modified at most once. There is a fuller description here:https://isocpp.org/wiki/faq/misc-technical-issues#double-mod-betw-seq-pt
As you can see from the FAQ, the ,
in the printf does not introduce a sequence point.
In the case of cout
this is different because there are 3 function calls to operator >>
. A function call introduces a sequence point therefore the modifications to memory location k
have a defined order. However (and this was a point I missed but Cubbi pointed out) because C/C++ doesn't define the order of evaluation of function arguments those arguments, even if they are functions, can be evaluated in any order the compiler defines. So in the expression:
f(h(), g())
Whether h() or g() is evaluated first is undefined: http://www.stroustrup.com/bs_faq2.html#undefined. So this is the reason why even in the case of cout you are getting different results from different compilers, basically because the cout << k++ << k << ++k
translates to cout.operator<<(k++).operator<<(k).operator(++k)
which is effectively an expression like this: f(h(g(cout, k++), k), ++k)
and each function argument is evaluated in an unspecified order.
You've got answers that cover the call to printf
but you're also asking why does the output of the cout
statement vary between compilers.
You're correct to say that it is equivalent to
( ( (cout<<k++)<<k)<<++k);
now, to evaluate that expression and obtain its result, the compiler must evaluate the rightmost <<
. Before the function call to that <<
can be made, its two operands, ( (cout<<k++)<<k)
and ++k
must be evaluated. And those two evaluations can occur in any order, or even simultaneously (compilers often interleave cpu instructions from two independent (as the compiler thinks) branches of code.
And since the evaluation of both expressions involves writing to k
, the behavior is undefined in case of the cout as well.
Actually, both printf and cout << are function calls, and C++ as well as C do not define an evaluation order for arguments. So the result for these test cases would vary from compiler to compiler, since its implementation defined.
精彩评论