Search code examples
cstatic-code-analysiscppcheck

Is the order of evaluation with comma operator & assignment in C predictable?


Recently cppcheck raised an error in some C code, that has the structure:

((void)(value_prev = value), value = new_value())

In most cases this can be split onto 2 lines, however there are some cases this is useful to have in a single statement.

In practice I found this works with popular compilers (GCC/Clang/MSVC), which don't give any warnings (even with warning levels set to their highest).


Example code:

#include <stdio.h>

int get_next(int i);

int main() {
    int i = 0, i_prev = 10;
    do {
        printf("%d\n", i);
    } while ((void)(i_prev = i),
             (i = get_next(i)) != 10);
}

CppCheck 1.73 (latest at time of writing) gives an error with this code:

(error) Expression '(void)(i_prev=i),(i=get_next(i))!=10'
depends on order of evaluation of side effects`

While the code could be changed to quiet the warning, is the order really undefined?


Solution

  • The order is defined, because there is a sequence point between them. See ISO/IEC 9899 6.5.17:

    The left operand of a comma operator is evaluated as a void expression; there is a sequence point after its evaluation. Then the right operand is evaluated; the result has its type and value. 95) If an attempt is made to modify the result of a comma operator or to access it after the next sequence point, the behavior is undefined.

    They then give an explicit example:

    In the function call
    f(a, (t=3, t+2), c)
    the function has three arguments, the second of which has the value 5.

    I'm not entirely sure why CppCheck is flagging it.