英文:
stack variable disappears at the last action of a function?
问题
尾递归的优势在于我们在代码的最后一个操作中再次调用函数(递归),因此不需要保存堆栈变量。
只要这样做,这个行为会是一样的吗?我不能确定字符串会保留在堆栈中而不会被清除?
void foo(char* c){
c[0]='b';
printf("%s",c);
}
void foo2(){
char str[]="aaa";
foo(str);
}
int main(){
foo2();
}
还是我可以确保在foo2
中的字符串会一直存在,直到函数结束(达到最终作用域)。我在询问的是str
,它是foo2
函数的局部变量,是否仍然可用,还是这个局部变量(str
)会在调用foo(str)
后被清除,因为在这个函数foo2
中没有更多的操作要执行。
我想了解的是在foo
中是否可能尝试使用一个不再可用的字符串。
输出:
baa
通过这个例子,我可以看到str
直到foo2
作用域的结束才消失,但我想知道这是否每次都会这样,如果是的话,这如何与尾递归的概念相符,尾递归也在最后一个操作中调用函数。
英文:
The advantage of tail recursion is that we call the function (recursion) again in the last action of the code, so the stack variables doesn't need to be saved.
So here do this will act the same? and I can't be sure that the string will stay In the stack and not will be cleaned?
void foo(char* c){
c[0]='b';
printf("%s",c);
}
void foo2(){
char str[]="aaa";
foo(str);
}
int main(){
foo2();
}
or I can be sure that the string in foo2
will stay until the function ends (gets to the end scope).
I am asking if str
that is local variable of function foo2
will still be available, or if this local variable (str
) will be cleaned because no more actions to do in this function foo2
after calling foo(str)
.
I want to understand if could be that in foo
I will try to use a string that is not available anymore.
Output:
baa
By just this example I can see that str
didn't disappear until got to the end of foo2
scope, but I want to know if this will be like this every time, and if yes how this makes sense with the idea of tail recursion that also calls a function in the last action.
答案1
得分: 1
是的,因为您在函数foo2
返回之前使用它。在调用foo
之后,foo2
将等待foo
返回。
您的示例不是递归。递归是指函数调用自身。尾递归的示例:
void foo(char *x, size_t n)
{
if(x[n])
{
x[n] = 'b';
printf("%s\n", x);
foo(x, n + 1);
}
}
int main(void)
{
char s[4] = "aaa";
foo(s, 0);
}
https://godbolt.org/z/66PTrrY83
尾递归是指函数在函数中的最后一个操作是调用自身。这种情况下,编译器可以更容易地优化掉递归(这是一种昂贵的操作)。在上面的示例中,启用优化后,编译器将完全消除递归。
英文:
> or I can be sure that the string in foo2 will stay until the function
> ends (get to the end scope).
Yes as you use it before the function foo2
returns. After the call to foo
foo2
will wait until foo
returns.
Your example is not a recursion of any kind. Recursion is when the function calls itself. Exmaple of tail recursion:
void foo(char *x, size_t n)
{
if(x[n])
{
x[n] = 'b';
printf("%s\n", x);
foo(x, n + 1);
}
}
int main(void)
{
char s[4] = "aaa";
foo(s, 0);
}
https://godbolt.org/z/66PTrrY83
Tail recursion if the function is calling itself as the last operation in the function. This case makes compilers work much easier as they can quite easily get rid of the recursion (which is expensive operation). In the case above when you enable optimizations the compiler will remove the recursion completely:
foo:
cmp BYTE PTR [rdi+rsi], 0
je .L6
push rbp
mov rbp, rdi
push rbx
mov rbx, rsi
sub rsp, 8
.L3:
mov BYTE PTR [rbp+0+rbx], 98
mov rdi, rbp
add rbx, 1
call puts
cmp BYTE PTR [rbp+0+rbx], 0
jne .L3
add rsp, 8
pop rbx
pop rbp
ret
.L6:
ret
main:
sub rsp, 24
xor esi, esi
lea rdi, [rsp+12]
mov DWORD PTR [rsp+12], 6381921
call foo
xor eax, eax
add rsp, 24
ret
答案2
得分: 0
我的问题是我不太了解尾调用优化,编译器会优化尾递归,但这与局部变量在离开作用域之前仍然可用的逻辑无关。
谢谢你的帮助。
英文:
My problem was that I didn't understand enough about tail call optimizations, the compiler optimizes tail recursion and this doesn't have anything about the logic that the local variable is available until leaving the scope.
ty for your help.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论