как рекурсия сохраняет значение даже после некоторого цикла - PullRequest
0 голосов
/ 31 января 2019

Кто-нибудь может объяснить выполнение этой программы.ВЫВОД: 1 2 3 4 3 2 1

как функция сохраняет значение 3,2,1 в конце

main(){
   int h=0;
    g(h);
}
 g(int n){
    n++;
    printf("%d\n",n);
    if (n ==4)return 88;
    g(n);
    printf("%d\n",n);
}

Ответы [ 4 ]

0 голосов
/ 31 января 2019

Вы можете прочитать выше ответы, они довольно хороши, но вот еще один способ, чтобы заставить вас задуматься.Простейший ответ - это то же самое, что функция-вызывающая функция сохраняет свое значение при вызове любой функции.Например, если у вас есть:

int main (void) {
    int a = 5;
    fun1 (a);
}

void fun1 (a) {
    fun2 (a);
    printf("%d\n", a); // output would be 5
}

void fun2 (int a) {
    a+=1;
    fun3 (a);
    printf("%d\n", a);
}

void fun3 (int a) {
    a+=1;
    printf("%d\n", a);
}

Итак, fun1 () выведет 5, fun2 () 6 и fun3() 7.Функция рекурсии похожа на описанную выше с точки зрения вызывающей и вызываемой функции, вместо вызова функции с другим именем она вызывает функцию с тем же именем или другими словами, она вызывает сама себя.

Посмотрите на этот код:

void recFun (int a) {
   if (a > 6)
       printf("%d\n", a);

   recFun (a + 1);

   printf("%d\n");
}

Некоторые люди, когда я учился в школе, переписывали вышеизложенное на следующее (на листе бумаги, конечно, это будет кричать на вас, если вы попытаетесь его скомпилировать):

void recFun (int a) {
   recFun (a + 1);

   printf("%d\n");
}

void recFun (int a) {
   recFun (a + 1);

   printf("%d\n");
}

void recFun (int a) {
   printf("%d\n");
}
0 голосов
/ 31 января 2019

Вы получаете вышеприведенный вывод, потому что в 8-й строке вашего кода вы рекурсивно вызываете функцию agian, поэтому оставшийся после 8-й строки код сохраняется в стеке вызовов в вашей памяти.Таким образом, когда вы получаете выходные данные 1 2 3 4, остающийся код, который остается (в стеке вызовов), выполняется, следовательно, вы получаете этот вывод.

ниже - стек вызовов вашей программы, когда n = 0стек поместит 1 |___| |___| |_1_| , когда n = 1, стек поместит 2 |___| |_2_| |_1_| , когда n = 2, стек разместит 3
|_3_| |_2_| |_1_| , когда n = 4, стек не будет ничего размещать, поскольку он встречает возвратТеперь у нас есть некоторые значения в нашем стеке

, поэтому программа начинает выталкивать самое верхнее значение в стеке (здесь n = 3) и продолжает выполнение с того места, на котором остановилась (то есть печатает значение), иэтот процесс будет продолжаться, пока стек не опустеет.

ПРИМЕЧАНИЕ. Вы можете посетить это видео, чтобы более эффективно понять рекурсию https://www.youtube.com/watch?v=Mv9NEXX1VHc

0 голосов
/ 31 января 2019

В C аргументы функции действуют как локальные переменные внутри функции.Далее C использует вызов по значению, что означает, что значение переменной, используемой вызывающей стороной в качестве аргумента, равно , скопировано в переменную аргумента функции.Следовательно, две переменные являются полностью независимыми переменными.

Рассмотрим этот код:

void foo(int x)
{
    x++;
    printf("%d", x);
}

void bar(int y)
{
    y++;
    printf("%d ", y);
    foo(y);
    printf("%d", y);
}

bar(0);

Это выведет "1 2 1"

Большинство людей считают, что изменения очевидныx не изменится y.Они по имени две разные переменные.Так что в этом нет ничего удивительного.

Если мы изменим код, чтобы использовать одно и то же имя для переменных - как:

void foo(int x)
{
    x++;
    printf("%d", x);
}

void bar(int x)
{
    x++;
    printf("%d ", x);
    foo(x);
    printf("%d", x);
}

bar(0);

Вывод все еще "1 2 1"

Просто потому, что переменная x внутри foo является другой переменной, чем x внутри bar.Единственное отношение, которое у них есть, это то, что x внутри foo инициализируется с копией значения x внутри bar.Независимо от того, какое изменение вы вносите в x внутри foo, оно не может / не может измениться x внутри bar.

Точно то же самое относится и к рекурсии.Каждый вызов функции создает свою собственную переменную n - полностью независимую от переменной n в предыдущих вызовах.

В большинстве реализаций для реализации этой функции используется стек.Выполните поиск «стека кадра», чтобы получить больше информации.Также см. Объясните концепцию стекового фрейма в двух словах

0 голосов
/ 31 января 2019
 g(int n){
    n++;
    printf("%d\n",n); // n=1 print 1 & call g(n) with 1 now g(1) make its own n=2 print 2 & call g(2) 
    //... print 3 & call g(3) becomes  4  print 4 return 88 
    if (n ==4)return 88;


    g(n);

     // now after the return we get back to the 3rd call that called g(3) 
     //so it print 3 at the end 3 ends 
     //we go back to the one that called g(2) so we print 2 at the end... & same for 1
    printf("%d\n",n);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...