ProgrammingLead C Developer, System Programmer

How is the reproduction of side effects during function argument evaluation implemented in C? What is the order of evaluation of arguments, and what unexpected issues can arise here?

Pass interviews with Hintsage AI assistant

Answer

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).

  • All expressions/side effects in the arguments must be completed before the function call, but there is no guarantee that they are executed in any specific order.
  • This means that using variables with value changes in multiple arguments is a potential source of undefined behavior or simply differences between architectures.

Example

void fn(int a, int b) { /* ... */ } int x = 1; fn(x++, x++); // the order of evaluation of x++ and x++ is not defined!

Trick Question

"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!

Examples of real errors due to ignorance of the nuances of the topic


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.