Объяснение с помощью рисунков

На следующих рисунках мы подробно рассмотрим следующий код:

float _pow_recursion(float x, float y)
{
    if (y == 0)
        return (1);
    if (y < 0)
        return (_pow_recursion(x, y + 1) / x);

    return (_pow_recursion(x, y - 1) * x);
}

Здесь вы видите рекурсивную функцию, которая вызывает саму себя. Он имеет 3 стадии выполнения, заданные как операторы. Первый возвращает значение 1, если наша переменная Y равна 0; второй выполняется, если Y меньше 0, а третий выполняется, если Y не ниже и не равен 0. Для целей этой статьи мы будем говорить, что наша переменная X равна 5, а наша переменная Y равна до 3.

Поскольку Y не меньше и не равно 0, наша функция будет вызывать себя снова и снова, каждый раз вычитая значение 1 из нашей переменной Y. Что интересно, Y в конце концов становится равным 0, и в этом случае выполняется оператор if, установленный для этого случая. С предыдущим изображением легко представить, что происходит с точки зрения нашей функции, но как насчет стека и как все это связано?

Стек — это место в памяти, в котором операции хранятся в порядке LIFO (последний пришел — первый ушел). Это означает, что операции в нашей функции хранятся, как показано выше. Наша функция в основном считает себя в обратном порядке (в нашем случае от 3 до 0), и когда она достигает нуля, она умножает X на количество раз, которое она прошла назад, то есть на 3. Это именно то, что мы делаем, когда нам нужно вычислить вывести число в степени другого числа (в нашем случае 5 в степени 3).

Пожалуйста, помните, что у нашей функции был своего рода «перерыв», состояние, при достижении которого рекурсия останавливается. Если бы у нашей функции был только третий случай, например:

float _pow_recursion(float x, float y)
{
    return (_pow_recursion(x, y - 1) * x);
}

У нас будет бесконечный цикл и то, что называется переполнением стека, потому что наша функция будет выполнять себя и занимать память снова и снова. Рекурсивные функции невероятно мощны, но при их использовании нужно быть осторожным.