首页 > 解决方案 > 何时/何处分配本地数组?

问题描述

https://www.gnu.org/software/libc/manual/html_node/Memory-Allocation-and-C.html描述了局部变量的自动分配。我知道局部变量通常分配在堆栈上。我可以想象如何int在堆栈上分配一个;只是推动它的价值。但是如何分配数组呢?

例如,如果您声明一个数组char str[10];,那 10 个字节的空间是在堆栈上,还是在其他地方分配,只有str指针被压入堆栈?如果是后者,这 10 个字节的空间分配在哪里?

此外,包括数组在内的局部变量究竟是什么时候分配的?我通常将堆分配称为“动态分配”,这意味着自动变量不是动态分配的。但是自动变量可以在控制流结构和函数体中声明,因此编译器不可能在运行前确切知道自动变量将占用多少空间。所以自动变量也必须是动态分配的,对吧?

编辑:我想强调这个问题的前半部分。我最感兴趣的是了解何时何地分配本地数组的空间。在堆栈上?别的地方?

编辑 2:当我最初为这个问题包含 C++ 标记时,我犯了一个错误。我的意思是只询问C语言及其实现。对于任何混淆,我深表歉意。

标签: carraysgccmemory

解决方案


在 C 2018 标准中,第 6.2.4 条第 6 和第 7 段告诉我们具有自动存储持续时间的对象的生命周期。第 6 段涵盖了不是可变长度数组的对象:

…它的生命周期从进入与其关联的块开始,直到该块的执行以任何方式结束。(进入封闭的块或调用函数会暂停,但不会结束当前块的执行。)如果递归地进入块,则每次都会创建对象的新实例。

因此,如果我们有以下代码:

{
    PointA;
    int x = 3;
    PointB;
}

那么x一旦执行到达就存在于C模型中PointA——进入它的块,这就是生命周期x开始的时候。然而,虽然x已经存在于PointA,但它的值是不确定的。初始化仅在达到定义时发生。

第 7 段告诉我们可变长度数组:

…它的生命周期从对象的声明开始,直到程序的执行离开声明的范围。

所以,如果我们有这个代码:

{
    PointA;
    int x[n]; // n is some variable.
    PointB;
}

那么x不存在于PointA。它的生命周期从int x[n];到达时开始。

请记住,这种存在只是根据 C 的抽象计算模型。只要可观察的结果(例如程序的输出)相同,编译器就可以优化代码。x因此,当输入块时,编译器生成的实际代码可能不会创建。(它可能根本不会创建x;它可以完全优化掉。)


推荐阅读