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.