Я думал, я понимаю, как точки последовательности работают в C++, но this GeeksQuiz question меня озадачило:Вызов функции с побочными эффектами внутри выражения
int f(int &x, int c) {
c = c - 1;
if (c == 0) return 1;
x = x + 1;
return f(x, c) * x;
}
int main() {
int p = 5;
cout << f(p, p) << endl;
return 0;
}
«Правильный» ответ на этот вопрос говорит, что печатает 6561. Действительно, в VS2013 оно делает. Но разве это не UB, потому что нет гарантии, которая будет оценена первой: f(x, c)
или x
. Мы получим 6561, если сначала оценивается f(x, c)
: все это превращается в пять рекурсивных вызовов: первые четыре (c = 5, 4, 3, 2
) продолжаются, последний (c = 1) завершается и возвращает 1, что в конце концов составляет 9 ** 4
.
Однако, если сначала оценивали x
, тогда мы бы получили 6 * 7 * 8 * 9 * 1
. Самое смешное, что в VS2013 даже замена f(x, c) * x
на x * f(x, c)
не изменит результат. Не значит, что это что-то значит.
В соответствии со стандартом, является это UB или нет? Если нет, то почему?
clang дает '3024' для' x * f (x, c) '(и' 6561' для 'f (x, c) * x'). – Holt