Ответ 1
Может ли кто-нибудь объяснить, почему printf выполняет или этот парень ошибается?
Потому что возвращается main
.
Этот ответ выписывает логику, но я вижу, что вы все еще спрашиваете об этом в комментариях. Поэтому я собираюсь сказать то же самое по-другому и надеюсь, что это яснее для вас.
Поскольку переменная static
, перед первым вызовом переменная объявляется и устанавливается в 4. Поскольку это static
, одна и та же переменная будет использоваться каждый раз. Он просто пропускает декларацию и инициализацию, если вызывается снова (или, вероятно, даже в первый раз, поскольку переменные static
могут быть выделены перед запуском).
В первом вызове переменная уменьшается до 3. 3 является правдивым значением, поэтому мы делаем блок if
. Это вызывает main
рекурсивно.
В этом втором вызове переменная уменьшается до 2. 2 по-прежнему правдива в C. Мы снова вызываем main
снова.
В этом третьем вызове переменная уменьшается до 1. 1 по-прежнему остается правдой. Мы снова возвращаемся к main
.
В этом четвертом вызове переменная уменьшается до 0. 0 false в C. Мы не вводим блок if
. Мы не возвращаемся. Мы не печатаем. В этом вызове нечего делать main
. Он возвращается в конце.
Теперь мы возвращаемся к третьему звонку. Мы только что вернулись с вызова на main
. Мы все еще находимся внутри блока if
. Следующий оператор - printf
. Значение переменной теперь равно 0. Итак, мы печатаем 0. Ничего не оставалось делать, мы возвращаемся в конце.
Теперь мы вернулись во второй раз. Тем не менее 0, поэтому мы печатаем еще один и возвращаем.
Теперь мы вернулись к первому звонку. Тем не менее 0, поэтому мы печатаем еще один и возвращаем.
Мы напечатали 0 три раза, поэтому 000
Как вы заметили, по пути вниз мы не печатаем. Мы печатаем на обратном пути. К этому времени переменная равна 0. И мы вводим затем блок if
три раза. Поэтому мы возвращаемся, а затем печатаем три раза.
Когда вы вызываете функцию рекурсивно, вы не устраняете предыдущий вызов. Вы положили его в стек. Когда закончите, вы вернетесь в то место, где вы ушли, и продолжайте со следующего заявления.
Возможно, вам захочется подумать о том, как следующие три части кода будут реагировать по-разному:
void recurse() {
static int i = 4;
if (--i) {
recurse();
printf("%d", i);
}
}
Распечатывает 000 при вызове в первый раз. После этого ничего не происходит.
void recurse(int i) {
if (--i) {
recurse(i);
printf("%d", i);
}
}
Будет напечатан 123, если он называется recurse(4)
. В качестве параметра мы имеем дело с другим i
каждый раз, когда вызывается функция.
void recurse(int i) {
if (--i) {
printf("%d", i);
recurse(i);
}
}
Печатает 321, если вызывается как recurse(4)
. Печать по пути вниз, а не при возврате.
void recurse(int i) {
printf("%d", i);
if (--i) {
recurse(i);
}
}
Печатает 4321, если вызывается как recurse(4)
. Он печатает на пути вниз, а не вверх.
void recurse() {
static int i = 4;
printf("%d", i);
if (--i) {
recurse();
}
}
Будет напечатан 4321. Мы печатаем по пути вниз, а не вверх. Обратите внимание, как параметр и переменная static
дают такой же результат. Однако, если это называется во второй раз, он ничего не сделает. Параметр снова напечатает то же самое.
void recurse() {
int i = 4;
if (--i) {
recurse();
printf("%d", i);
}
}
Петли навсегда. Без static
каждый раз мы делаем новый i
. Это будет работать до тех пор, пока не перегрузит стек и не сработает. Нет вывода, потому что он никогда не попадает в printf
.
Самый простой способ проверить это - пойти куда-нибудь, как ideone.com, и запустить код. Спросить, почему он печатает что-то, является разумным для этого сайта. Но спрашивать, что он печатает, - это то, на что вы должны ответить самим.