Order of evaluation of the operands of any C (does apply for Objective C and C++) operator is unspecified (except where noted below). This includs the order of evaluation of function arguments in a function-call expression and the order of evaluation of the subexpressions within any expression. The compiler will evaluate them in any order and may choose another order when the same expression is evaluated again.
Why is it good? It simplifies the compiler’s job, making it possible to generate very efficient code in certain situations.
Why is it evil? Side effects! They depend upon not only specific hardware, platform and compiler but also on specific settings (optimization level, debug / release version) of the same compiler. This results in unportable code and bugs hard to detect.
• Order of evaluation of the operands of any operator (e.g. +, -, =, *, /)
- logical operators (&& and ||)
- logical operator (?:)
- comma operator ,
Surprisingly the output could be any of the following: „1 2 3“, „2 1 3“, „3 2 1“, „2 1 3“, „1 3 2“ and „3 1 2“!
The expression f1() + f2() + f3() is parsed as (f1() + f2()) + f3() due to left-to-right associativity of operator+, but the function call to f3 may be evaluated first, last, or between f1() or f2() at run time.
Order of evaluation of function arguments in a function-call expression
- The result with clang / ppc architecture
- The result with clang / i386 architecture
The next section contains the solution to the problem.
Do not write code that depends on evaluation order (has side effects).
- Enable and heed compiler warnings
- Use static analyzers (like clang’s, cppcheck, etc.) to get even more warnings
Unspecified behavior is behavior that may vary on different implementations of a programming language. The exact behavior may not be completely determined upon examination of the program's source code.
Andreas Maier, Software architect, Business Division Banking & Insurance