In C, the order of evaluation of function arguments is not defined by the standard (up to and including C99). Arguments may be evaluated from left to right, right to left, or in any other order (at the discretion of the compiler or architecture).
void fn(int a, int b) { /* ... */ } int x = 1; fn(x++, x++); // the order of evaluation of x++ and x++ is not defined!
"In what order are function arguments evaluated in C, and can this be relied upon when writing code?"
A common mistake is to assume that arguments are evaluated from left to right (similar to expressions). In practice, each function call is compiled at the discretion of the compiler (and platform).
void foo(int a, int b, int c); int x = 1; foo(x++, x++, x++); // the result depends on the order of argument evaluation
The real answer: you cannot rely on it — behavior is undefined!
Story
In a multi-platform product, a programmer wrote
push(stack, stack->size++, data);. It worked on most platforms, but on one, the stack size increased before data was passed, while on another it increased after. Data was "lost" or addressed incorrectly, the error occurred rarely and was very difficult to debug.
Story
In the network protocol library, the logging function was called with argument expressions incrementing statistical counters. The statistical reports were generated incorrectly: for different clients, the indices of the counters differed because they were not executed in the expected order.
Story
In the hardware control interface, the initialization function passed pointers and offsets with increments inside arguments (like
init(ptr++, cnt++);). On some processors, the hardware was initialized correctly, while on others, it failed, with the cause being long sought in the hardware, even though the problem lay in the incorrect C code.