Другие ответчики правы, что есть некоторая магия компилятора, которая преобразует хвостовую рекурсию в итерацию, хотя это зависит от настроек оптимизации компилятора. Например, в gcc, если мы скомпилируем с gcc -S -O1 someFile.c
(учитывая ваш код), мы получим следующую сгенерированную сборку:
fun:
.LFB2:
pushq %rbp
.LCFI0:
movq %rsp, %rbp
.LCFI1:
movl $0, %eax
call fun
leave
ret
.LFE2:
.size fun, .-fun
Итак, вы можете видеть, что он по-прежнему использует инструкции call / exit / ret для выполнения фактического вызова функции, что приведет к остановке процесса. Как только вы начинаете дальнейшую оптимизацию с помощью gcc -S -O2 someFile.c
, мы начинаем понимать:
fun:
.LFB24:
.p2align 4,,10
.p2align 3
.L2:
jmp .L2
.LFE24:
.size fun, .-fun
.p2align 4,,15
Это зависит от вашего компилятора и настроек компилятора, поэтому с ними полезно дружить.