Предсказуем ли порядок оценки с оператором запятой и назначением в C?

недавно cppcheck вызвал ошибку в некотором коде C, который имеет структуру:

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

в большинстве случаев это можно разделить на 2 строки, однако в некоторых случаях это полезно иметь в одном операторе.

на практике я обнаружил, что это работает с популярными компиляторами (GCC/Clang/MSVC), которые не дают никаких предупреждений (даже с уровнями предупреждения, установленными на самый высокий).


пример кода:

#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 (последний на момент написания) дает ошибку с этим кодом:

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

В то время как код может быть изменен, чтобы успокоить предупреждение, действительно ли порядок не определен?

1 ответов


порядок определен, потому что между ними есть точка последовательности. См. ISO / IEC 9899 6.5.17:

левый операнд оператора запятой оценивается как void выражение; существует точка последовательности после ее оценки. Затем вычисляется правильный операнд; результат имеет свой тип и значение. Девяносто пять) Если предпринята попытка изменить результат оператора запятой или доступ к нему после следующей точки последовательности, поведение не определено.

затем они дают явный пример:

при вызове функции
f(a, (t=3, t+2), c)
функция имеет три аргументы, второй из которых имеет значение 5.

Я не совсем уверен, почему CppCheck помечает его.