если бы вызовы функции самостоятельно при определении переменных одновременно это привело бы к переполнению стека? Есть ли любая опция в gcc для многократного использования того же стека.
void funcnew(void)
{
int a=10;
int b=20;
funcnew();
return ;
}
действительно ли функция может снова использовать стековый фрейм, который она использовала ранее? Какова опция в gcc для многократного использования того же кадра в хвостовой рекурсии??
Да. См. раздел
-foptimize-silbling-calls
Оптимизация одноуровневых и конечных рекурсивных вызовов.
Включено на уровнях -O2, -O3, -Os.
Ваша функция компилируется в:
funcstack:
.LFB0:
.cfi_startproc
xorl %eax, %eax
jmp func
.cfi_endproc
(обратите внимание на переход к func)
Повторное использование кадра стека при завершении функции вызовом - это включает в себя в своем полном обобщении манипулирование стеком, чтобы поместить параметры в правильное место и заменить вызов функции прыжком к началу функции - это хорошо известная оптимизация, называемая [i] удаление хвостового вызова [/i]. Это предписано некоторыми языками (например, схема) для рекурсивных вызовов (рекурсивный вызов является естественным способом выражения цикла в этих языках). Как указано выше, gcc имеет оптимизацию, реализованную для C, но я не уверен, какой другой компилятор имеет его, я бы не зависел от него для портативного кода. И обратите внимание, что я не знаю, какие ограничения на него есть - я не уверен, например, что gcc будет манипулировать стеком, если типы параметров различны.
-121--3977986-По одному приложению для каждого экрана/ subdomain.heroku.com.
-121--2561257-Да, в некоторых случаях компилятор может выполнить оптимизацию хвостового вызова . Необходимо ознакомиться с руководством компилятора. (AProgrammer, похоже, процитировал руководство GCC в своем ответе.)
Это существенная оптимизация при внедрении, например, функциональных языков, где такой код встречается часто.
Нет, каждая рекурсия - это новый кадр стека. Если рекурсия бесконечно глубока, тогда необходимый стек также бесконечен, поэтому вы получите переполнение стека.
Вы не можете полностью отказаться от кадра стека, так как он необходим для адреса возврата. если вы не используете хвостовую рекурсию, и ваш компилятор не оптимизировал ее до цикла. Но если быть полностью технически честным, вы можете избавиться от всех переменных в кадре, сделав их статическими. Однако это почти наверняка не то, что вы хотите делать, и вам не следует делать это, не зная точно, что вы делаете, чего вы не делаете, поскольку вам приходилось задавать этот вопрос.
Да. См.
-foptimize-sibling-calls
Оптимизация одноуровневых и хвостовых рекурсивных вызовов.
Включено на уровнях -O2, -O3, -Os.
Ваша функция скомпилирована в:
funcstack:
.LFB0:
.cfi_startproc
xorl %eax, %eax
jmp func
.cfi_endproc
(обратите внимание на переход к функции)
Повторное использование кадра стека, когда функция завершается вызовом - это включает в себя в полной мере манипулирование стеком для помещения параметров в правильное место и замена вызова функции переходом к началу функции - это хорошо известная оптимизация под названием [i] удаление хвостового вызова [/ i].Некоторые языки (например, схема) требуют его для рекурсивных вызовов (рекурсивный вызов - это естественный способ выразить цикл на этих языках). Как указано выше, в gcc реализована оптимизация для C, но я не уверен, в каком другом компиляторе она есть, я бы не зависел от нее для переносимого кода. И обратите внимание, что я не знаю, какие ограничения есть на это - я не уверен, например, что gcc будет манипулировать стеком, если типы параметров разные.
Даже без определения параметров вы получите переполнение стека. Поскольку адрес возврата также помещается в стек.
Возможно (я узнал об этом недавно) возможно, что компилятор оптимизирует ваш цикл до хвостовой рекурсии (что заставляет стек вообще не расти). Ссылка на вопрос о хвостовой рекурсии в SO