Я бы использовал попытку "снизу вверх":
baz
- это функция, которая вызывается, но не вызывает другие функции (кроме себя). Он выводит 'Z' ровно y + 1
раз, код возврата - x*y
(вы добавляете x
после каждого вызова).
bar
- это «следующая более высокая» функция, она выводит «B» один раз и вызывает baz
с нижним аргументом в качестве второго параметра - код возврата тоже x*y
.
foo
- это «верхняя» функция (сразу после main
) и ее самая сложная функция. Он выводит 'F' не только один раз, но a
раз (из-за foo(a-1)
в конце, который оценивается перед вызовом bar
. Вызов bar
умножает a
и foo(a-1)
, что будет умножать a-1
и foo(a-2)
и так далее до тех пор, пока foo(1)
не будет вычислено и не вернет 1. Таким образом, код возврата равен a * (a-1) * ... 2 * 1
, поэтому a!
.
Это не полный анализ, например мы не знаем, в каком порядке будут выводиться символы, но это грубая схема того, что происходит - и, как вы и другие люди в комментариях указали, это то, что вы хотите - тактика вместо полного ответа.