代码之家  ›  专栏  ›  技术社区  ›  Anton Quelle

堆栈上的C数组

  •  0
  • Anton Quelle  · 技术社区  · 7 年前

    在c(和c++)中,可以通过以下方式创建整数数组:

    int a[const];
    

    其中const是编译时常量,或

    int *a = (int *) malloc(...);
    

    根据我的理解,第一个在堆栈上分配内存,第二个在堆上分配内存。现在,据我所知,堆栈上的内存是按顺序排列的,这样程序就可以根据需要将其从顶部弹出。这意味着数组中的元素不一定按顺序存储,这听起来很奇怪。

    这里到底发生了什么?

    编辑:

    感谢各位的回复。通过你的回答和一些后续的谷歌搜索,我找到了困惑的根源。我假设程序只会真正使用堆栈的top变量,然后逐个打开/关闭它们。

    3 回复  |  直到 7 年前
        1
  •  6
  •   AnT stands with Russia    7 年前

    虽然抽象C语言没有说明如何分配本地对象(即没有明确引用“堆栈”语言规范),但本地对象的存储时间与堆栈的后进先出属性很好地一致:本地对象按与其创建相反的顺序销毁。创建的对象 最后的 被摧毁 第一 反之亦然。

    此原则统一适用于所有局部对象。阵列也不例外。每个数组只是一个大小适当的连续内存字节块(顺便说一句,对于任何类型的对象都是如此)。数组没有什么特别之处。没有理由不按顺序存储数组元素。

    每个数组对象都是在堆栈顶部整体创建的。当array对象到达其存储持续时间的末尾时,它会像您所说的那样“弹出顶部”。任何可能在堆栈中位于其上方的内容都应该在那一刻被弹出。

        2
  •  2
  •   David Hoelzer    7 年前

    你可能误解了什么。

    实际上,堆栈始终是顺序存储。然而,堆栈的大小将远比堆的大小有限。虽然确实从堆栈中“弹出”了一些内容,但这实际上不适用于声明本地数组的函数。

    另一方面,堆可以增长。内存不足时, malloc 实现将调用 sbrk() 请求额外内存。这意味着,总的来说,堆不需要是连续的,尽管在调用 马洛克 realloc ,您可以确信内存将至少与您请求的内存一样大,并且地址将是连续的(至少从您的角度来看)。

        3
  •  0
  •   Jonathan Leffler    7 年前

    编程中有3种主内存类型:静态内存、堆和堆栈。

    静态内存用于分配所有“静态”变量,即在全局范围内声明或在函数中声明为静态的变量。这意味着静态变量的数量及其大小在编译时是已知的,编译器只为它们保留内存。

    堆是一个动态内存池,您可以在需要时借用内存并将内存返回给它。因此,当您借用内存时,即“malloc”它,您可以随心所欲地使用它,直到您返回(释放)它,以便它可以被程序的不同部分重用。

    堆栈是一个特殊的内存区域,用于为函数分配局部变量。当您调用具有非静态局部变量的函数时,它将在内存中为这些变量分配足够的空间(加上函数所需的额外空间)。当您从函数返回时,内存会自动返回到系统,以便在另一个函数调用中重用。

    在您的情况下,第一个声明可以是静态变量,也可以是局部函数变量。根据这一点,它可以分配到其中一个池中。第二种情况是从堆借用内存。

    通常每个变量都会占用内存中连续的空间。它是哪种类型的内存并不重要。数组就是这样一个占用内存区域的变量。数据放入内存的顺序取决于体系结构。编译器的任务是为您提供变量的标准视图,即数组[0]应包含数组[0]的数据,指针算法应以标准方式工作。

    因此,实际上,数组的所有元素都是按顺序存储的。如果没有,则不会改变编程中的任何内容。虽然我还没有看到过这样的情况。