编程语言入门/栈
外观
< 编程语言入门
也许,程序中最常见的变量是局部变量,也称为自动变量。在我们的例子中,变量`auto_var`和`auto_const`是局部变量。这些变量具有局部作用域:它们只存在于声明它们的函数内部,并且在函数返回时会丢失它们的值。但是,为什么呢?
每次调用函数时,都会创建一个名为激活记录(或栈帧)。激活记录是栈的一部分,用于在函数调用时存储函数的数据。因此,激活记录存储函数的参数、局部变量、返回地址等。函数的激活记录仅在函数运行时存在。结束后,其激活记录会被销毁,从而销毁函数数据。这就是为什么局部变量每次函数结束时都会丢失其值的原因。(记住:静态变量不会以这种方式工作。它们不是存储在栈中,而是存储在数据或bss部分)。
正如我们在之前的图片中所展示的那样,栈向下增长,而堆向上增长。这意味着如果在栈上分配了两个对象,第二个对象的地址将低于第一个对象的地址。
想象一下一个邮递员在一条街上送邮件。如果他从街道的尽头开始送邮件,朝着起点走,他将首先送住在房屋编号更高的那些人的邮件。这就是栈分配的工作方式:首先分配的对象具有更高的地址。堆分配的类比是相同的。唯一的区别是邮递员将从街道的起点开始送邮件,并朝着尽头走,从而首先送住在地址较低的人的邮件。
下面我们提供了一个小例子来展示它的工作原理。当我们运行下面的程序时,我们看到变量`aux_1`的地址大于`aux_2`的地址,而`aux_2`的地址大于`aux_3`的地址。
#include <stdio.h>
int sum(int a, int b) {
int aux_1 = a;
int aux_2 = b;
int aux_3;
printf("&aux_1 = %lu\n", &aux_1);
printf("&aux_2 = %lu\n", &aux_2);
printf("&aux_3 = %lu\n", &aux_3);
aux_3 = aux_1 + aux_2;
return aux_3;
}
int main() {
printf("Sum = %d\n", sum(2, 3));
}