Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 216
ideasman42 Avatar asked Apr 30 '16 02:04

ideasman42


People also ask

What is the order of evaluation of the operators?

Only the sequential-evaluation ( , ), logical-AND ( && ), logical-OR ( || ), conditional-expression ( ? : ), and function-call operators constitute sequence points, and therefore guarantee a particular order of evaluation for their operands.

What is the use of comma operator?

The comma operator ( , ) evaluates each of its operands (from left to right) and returns the value of the last operand. This lets you create a compound expression in which multiple expressions are evaluated, with the compound expression's final value being the value of the rightmost of its member expressions.

Are IF statements evaluated in order?

The if statements are evaluated in order until one of the if expressions is true or the end of the if/else if chain is reached. If the end of the if/else if chain is reached without a true expression, no code blocks are executed.

What is the typical evaluation order for an assignment expression?

The Usual Order ..., when evaluating the operands of an expression, assignment, or return statement, all function calls, method calls, and (channel) communication operations are evaluated in lexical left-to-right order.


1 Answers

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.

like image 106
Cort Ammon Avatar answered Sep 30 '22 18:09

Cort Ammon