каково различие между в то время как (1) бесконечный цикл и рекурсивная функция?

6
задан 3 March 2010 в 19:20
поделиться

10 ответов

Рекурсивная функция будет вызывать себя многократно. Бесконечный цикл будет просто продолжать выполнять один и тот же код многократно. Хотя это может звучать очень похоже, фактические эффекты очень разные. Каждый раз, когда вызывается метод, переменные заталкиваются в стек. Конечно, это означает, что существуют ограничения на количество повторений функции. Поэтому, хотя ваш бесконечный цикл будет выполняться вечно, рекурсивная функция на практике в конце концов исчерпает место в стеке, и приложение, скорее всего, остановится.

14
ответ дан 8 December 2019 в 03:09
поделиться

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

Цикл while просто вернется наверх и снова будет использовать то же пространство, так что он может работать буквально вечно (по крайней мере, пока не отключится электричество: -))

8
ответ дан 8 December 2019 в 03:09
поделиться

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

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

Примите во внимание

#include <stdlib.h>
#include <stdio.h>

int somefunc(int x) {
    printf("%d\n", x);
    return somefunc(rand());
}

int main(void) {
    return somefunc(0);
}

Вышеупомянутая программа в конечном итоге завершится или нанесет серьезный ущерб, в отличие от

int somefunc(int x) {
    return printf("%d\n", x);
}

int main(void) {
    while ( 1 ) {
        somefunc(rand());
    }
    return 0;
}

, которая будет успешно работать до тех пор, пока пользователь не завершит работу (нажатием CTRL-C или выключением компьютера .)

3
ответ дан 8 December 2019 в 03:09
поделиться

Когда функция вызывается, для нее выделяется некоторая память в стеке. Он сохраняет: - значения параметров, переданные в функцию - адрес возврата - адрес в памяти, по которому будет выполняться выполнение после возврата функции - локальные переменные - другие вещи которые зависят от реализации

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

В случае while (1) - процесс, выполняющий программу с бесконечным циклом, например, while (1) {;} просто повторяет некоторую часть команд. Поддержание такого процесса в рабочем состоянии в операционной системе, что просто требует времени процессора и некоторой памяти.

0
ответ дан 8 December 2019 в 03:09
поделиться

функция помещает в стек адрес возврата (место в памяти, откуда была вызвана следующая рекурсивная функция) и переходит к этому месту в памяти (к рекурсивной функции). {{1 }} И while не нужно хранить адрес ret, потому что он перескакивает только в начало.

0
ответ дан 8 December 2019 в 03:09
поделиться

Для простого кода и хорошего компилятора нет разницы, но для наивного компилятора с непрерывной рекурсивной функцией у вас закончится место в стеке , называется переполнением стека.

Что касается вопросов о том, что происходит: при переполнении стека: стек отображается в место или в память (для каждого процесса), рядом с которой не выделена память. Стек используется для хранения значений локальной функции, текущий адрес возврата функции также помещается в стек, а затем значения, переданные следующей функции, помещаются в стек. Таким образом потребляется стек для каждого вызова функции. Поэтому, когда ЦП пытается получить доступ к памяти, проходит конец выделенного пространства, что вызывает исключение доступа к памяти и интерпретируется как переполнение стека.

Некоторое время (1) поведение операционной системы зависит от того, какой режим многозадачности использует ваша ОС.Для упреждающей системы (например, Window NT и новее) он просто видит, что вашему процессу предстоит много работы, но если у него есть пользовательский интерфейс, и вы не отвечаете на отправляемые им оконные сообщения, вы получить классическое сообщение «Кажется, это приложение перестало отвечать».

Где, как если бы у вас была операционная система без упреждения, она зависнет, если вы не вернете управление ОС, то есть в дни Windows 3.1 драйвер принтера зависал бы во время печати всей системы. Ну, драйверы HP сделали.

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

0
ответ дан 8 December 2019 в 03:09
поделиться

в то время как (1) не создает новый контекст оценки, рекурсия (если не оптимизирована компилятором) создает. Это означает несколько вещей:

  • Во всех практических реализациях рекурсия достигает предела, когда новый контекст оценки не может быть создан (т. Е. Происходит переполнение стека).
  • Новый контекст оценки означает новые копии любых объявляемых вами локальных переменных.
  • Тривиально выйти из while (1) одним простым return , но return только выходит из текущего контекста в рекурсии. Не так просто полностью выйти из множества вложенных контекстов.
0
ответ дан 8 December 2019 в 03:09
поделиться

Рекурсивная функция может закончиться в зависимости от того, как она закодирована. Конечно, она не обязательно должна заканчиваться переполнением стека. while(1) Цикл также может завершиться, если в нем есть прерывание или возврат.

3
ответ дан 8 December 2019 в 03:09
поделиться

У рекурсивной функции есть пункт, в котором она не вызывает сама себя, что означает, что она заканчивается.

1
ответ дан 8 December 2019 в 03:09
поделиться

В бесконечном цикле while (1) выделяет пространство стека для кадра стека (информация о том, куда вернуться, если / когда функция вернется ), и любые локальные переменные, объявленные в той же функции, будут размещены в стеке один раз, независимо от того, сколько итераций выполняет цикл.

Следовательно, для 1000000 итераций пространство стека будет размером sizeof (кадр стека) + sizeof (любые локальные переменные)

, поэтому, если кадр стека равен 16 байтам, а int равен 4 байтам, функция будет выделять 20 байтов на стек.

Принимая во внимание, что рекурсивная функция будет выделять пространство в стеке для кадра стека (информация о функции, в которую нужно вернуться) и любых локальных переменных каждый раз, когда функция вызывает себя.

Следовательно, для 1000000 итераций пространство стека будет (sizeof (кадр стека) + sizeof (любые локальные переменные)) * 100000

, поэтому (с использованием предыдущих размеров) 20 байтов * 1000000 == 20000000 байтов = = (приблизительно) 19 МБ

1
ответ дан 8 December 2019 в 03:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: