4.4 C和C++中的栈使用
C 和 C++ 都会使用栈(stack)。例如,栈中通常保存以下内容:
- 函数的返回地址。
- 必须保存的寄存器,这些由 KF32编译器的调用约定决定。
- 局部变量,包括局部数组、结构体和联合体。
- C++ 中的类实例
有些栈使用情况并不直观,例如:
- 如果局部整型或浮点变量溢出寄存器(spilled),也就是未分配到寄存器,它们会分配到栈上。
- 结构体通常分配在栈上。栈上会保留一块大小为 sizeof(struct) 的空间。但是,编译器也可能尝试将结构体分配到寄存器中。
- 如果数组的大小在编译时已知,编译器会将其分配到栈上。栈上会保留一块大小为 sizeof(array) 的空间
- 一些优化可能会引入新的临时变量,用于保存中间结果。这些优化包括:公共子表达式消除(CSE, Common Subexpression Elimination)、活跃区间拆分(Live Range Splitting)、结构体拆分(Structure Splitting),编译器会尝试将这些临时变量分配到寄存器中。如果寄存器不足,则会将其溢出到栈上。
- KF32编译器要求某些函数参数通过栈传递,而不是寄存器传递。具体取决于参数的类型、大小以及参数顺序。
4.4.1 减少栈使用量的方法
在嵌入式系统中,栈空间有限,因此在编写应用程序时,尽量减少栈使用量可以提高系统的可靠性和性能。以下是常用方法:
- 编写只需要少量变量的小函数
- 避免使用大型局部结构体和数组
- 避免递归
- 尽量减少函数中每个时刻正在使用的变量数量
- 使用 C 语言的块作用域语法,并仅在需要时声明变量,以便不同作用域可以共享同一块内存