The order in which function arguments are evaluated before the function is called is unspecified behavior. You are assuming a sequence point between each argument, but that is not specified by the C Standard (C99, §6.5.2.2-10):
The order of evaluation of the function designator, the actual
arguments, and subexpressions within the actual arguments is
unspecified, but there is a sequence point before the actual call.
In C17, §6.5.2.2-10 the wording is different, but the result the same as far as this question is concerned:
There is a sequence point after the evaluations of the function
designator and the actual arguments but before the actual call. Every
evaluation in the calling function (including other function calls)
that is not otherwise specifically sequenced before or after the
execution of the body of the called function is indeterminately
sequenced with respect to the execution of the called function.
This means that the compiler is free to evaluate function arguments in any order, so on a different system, a different compiler or the same compiler with different options enabled, you may see a different result corresponding to a different order of evaluating the function arguments.
Note that the order of evaluation of arguments is unspecified behavior, not undefined behavior.
However, having more than one (sub)expression modifying the same variable without being separated by a sequence point is undefined behavior. C17, §6.5-2:
If a side effect on a scalar object is unsequenced relative to either
a different side effect on the same scalar object or a value
computation using the value of the same scalar object, the behavior is
undefined. If there are multiple allowable orderings of the
subexpressions of an expression, the behavior is undefined if such an
unsequenced side effect occurs in any of the orderings.
Hence, the first two printf
-statements having more occurrences of a++
have undefined behavior and thus the C Standard does not guarantee any outcome of the program.