函数的调用机制_用递归实现栈(Function call machenism_Recursive calls stimulate stack)

      函数调用包括函数代码间的双向数据传递执行控制转移数据传递通过函数参数和返回值来进行。另外,我们还需要在进入函数时为函数的局部变量分配存储空间,并且在退出函数时收回这部分空间,存储空间的分配与回收则通过栈操作来实现。控制转移”CPU都提供相应的指令,如,CALL ,RET 等。

     

      当调用以个函数时:

1)开辟该函数的栈空间(STACK FRAME);

2)将当前运行状态压栈;

3)将返回地址(函数调用的地方)压栈;

4)在栈内分配参数空间,传递参数信息;

4)执行被调用函数,如果有局部变量,则在栈内分配空间。(控制转交给被调函数)

 

 

假设函数A调用了函数B,栈内情况变化如下图所示:

函数的调用机制_用递归实现栈(Function call machenism_Recursive calls stimulate stack)_第1张图片

 

 

 

当函数运行结束,退栈操作与函数调用相反;

1)释放内部局部变量的空间;

2)释放栈内参数空间;

3)退栈,得到返回地址,程序跳转到A处等待继续执行;

4)退栈,得到程序运行时候的状态,恢复调用函数前的状态;

5)释放该函数的栈空间。

 

 

备注:并不是所有的局部变量都保存在栈中,有时会保存在寄存器中,函数返回值也是一样

Intel CPU 采用了所有函数必须遵守的寄存器用法统一惯例。该惯例指明,寄存器eaxedxecx的内容必须由调用者自己负责保存。当函数BA调用时,函数B可以在不用保存这些寄存器内容的情况下任意使用它们而不会毁坏函数A所需要的任何数据。另外,寄存器ebxesiedi的内容则必须由被调用者B来保护。当被调用者需要使用这些寄存器中的任意一个时,必须首先在栈中保存其内容,并在退出时恢复这些寄存器的内容。因为调用者A(或者一些更高层的函数)并不负责保存这些寄存器内容,但可能在以后的操作中还需要用到原先的值。还有寄存器ebpesp也必须遵守第二个惯例用法。

 

 

用递归模拟栈:

如果要实现读取一个字符串,逆序输出,即符合栈先入后出的特点。

函数调用-->栈,用递归函数调用模拟栈

 Code Sample:

#include <iostream> using namespace std; void stack(char ch); void main() { char c; cin >> c; stack(c); cout << endl; } void stack(char c){ if(c != '#'){ char d; cin >>d; stack(d); cout << c; } }

待更新。。。。

你可能感兴趣的:(c,function,存储)