C 中的静态变量如何在内存中持久化?

Ben*_*min 1 c static

我们都知道静态变量如何工作的常见示例 - 在具有某个值(假设为 5)的函数内声明了一个静态变量,该函数将其加 1,并且在对该函数的下一次调用中,该变量将被修改值(在我的示例中为 6)。

这在幕后是如何发生的?是什么让函数在第一次调用后忽略变量声明?鉴于函数的堆栈帧在调用完成后被“销毁”,该值如何保留在内存中?

Lun*_*din 7

static变量和其他具有静态存储期限的变量存储在堆栈外部的特殊段中。一般来说,C 标准除了在调用 main() 之前初始化静态存储持续时间变量之外,没有提及这是如何完成的。然而,现实世界中绝大多数计算机的工作方式如下:

如果使用值初始化静态存储持续时间变量,则大多数系统将其存储在名为 的段中.data。如果您不初始化它,或者显式地将其初始化为零,它将存储在另一个称为“.bss所有内容都初始化为零”的段中。

需要理解的棘手部分是,当我们编写如下代码时:

void func (void)
{
  static int foo = 5;   // will get stored in .data
  ...
Run Code Online (Sandbox Code Playgroud)

然后,包含初始化的行在第一次进入函数时不会执行(正如初学者课程中经常教授的那样) - 它根本不在函数内部执行,并且在函数执行期间始终被忽略。

在调用 main() 之前,“C 运行时库”(通常称为 CRT)会运行各种启动代码。这包括将值复制到.data和中.bss。所以上面的行实际上是在程序启动之前执行的。

func()所以到第一次调用的时候,foo已经初始化了。与任何其他变量foo一样,函数内部的任何其他更改都将在运行时发生。

此示例说明了程序的各个内存区域。栈和堆上分配了什么?给出了更通用的解释。


Bar*_*mar 5

该变量不存储在堆栈帧中,它存储在用于全局变量的同一内存中。唯一的区别是变量名的作用域是声明变量的函数。