stack variable disappears at the last action of a function?

90 Views Asked by At

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.

2

There are 2 best solutions below

0
Daniel Zaken On BEST ANSWER

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.

1
0___________ On

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