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?
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.
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With