返回
函数栈帧的创建和销毁,入门C语言的进阶之路
后端
2023-09-23 19:00:37
函数栈帧的创建
当一个函数被调用时,系统会在内存中创建一个栈帧。栈帧是一个数据结构,它存储着函数调用所需的信息,包括:
- 函数的参数
- 局部变量
- 返回地址
栈帧的创建过程如下:
- 系统会将函数的参数压入栈中。
- 系统会将函数的局部变量压入栈中。
- 系统会将函数的返回地址压入栈中。
栈帧的创建过程如下图所示:
+----------------+
| 返回地址 |
+----------------+
| 局部变量 1 |
+----------------+
| 局部变量 2 |
+----------------+
| ... |
+----------------+
| 参数 1 |
+----------------+
| 参数 2 |
+----------------+
| 参数 3 |
+----------------+
函数栈帧的销毁
当一个函数返回时,系统会销毁它的栈帧。栈帧的销毁过程如下:
- 系统会将函数的局部变量弹出栈。
- 系统会将函数的参数弹出栈。
- 系统会将函数的返回地址弹出栈。
栈帧的销毁过程如下图所示:
+----------------+
| 返回地址 |
+----------------+
| 局部变量 1 |
+----------------+
| 局部变量 2 |
+----------------+
| ... |
+----------------+
| 参数 1 |
+----------------+
| 参数 2 |
+----------------+
| 参数 3 |
+----------------+
函数栈帧的应用
函数栈帧在C语言中有着广泛的应用,包括:
- 参数传递
- 局部变量
- 递归调用
参数传递
当一个函数被调用时,它的参数会被压入栈中。这使得函数可以访问它的参数。
例如,以下函数的两个参数x
和y
会被压入栈中:
int add(int x, int y) {
return x + y;
}
当add()
函数被调用时,栈帧如下图所示:
+----------------+
| 返回地址 |
+----------------+
| y |
+----------------+
| x |
+----------------+
局部变量
函数的局部变量也会被压入栈中。这使得函数可以访问它的局部变量。
例如,以下函数的局部变量sum
会被压入栈中:
int add(int x, int y) {
int sum = x + y;
return sum;
}
当add()
函数被调用时,栈帧如下图所示:
+----------------+
| 返回地址 |
+----------------+
| sum |
+----------------+
| y |
+----------------+
| x |
+----------------+
递归调用
当一个函数调用自身时,称为递归调用。递归调用会导致栈帧不断被创建和销毁。
例如,以下函数的递归调用会导致栈帧不断被创建和销毁:
int factorial(int n) {
if (n == 0) {
return 1;
} else {
return n * factorial(n - 1);
}
}
当factorial()
函数被调用时,栈帧如下图所示:
+----------------+
| 返回地址 |
+----------------+
| n |
+----------------+
当factorial()
函数递归调用自身时,另一个栈帧会被创建:
+----------------+
| 返回地址 |
+----------------+
| n-1 |
+----------------+
这个过程会一直重复,直到n
等于0。
总结
函数栈帧是C语言中一个重要的数据结构。它存储着函数调用所需的信息,包括函数的参数、局部变量和返回地址。函数栈帧在参数传递、局部变量和递归调用中都有着广泛的应用。