堆栈上的C数组

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了堆栈上的C数组相关的知识,希望对你有一定的参考价值。

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

int a[const];

const是编译时常量,或者

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

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

究竟是什么发生在这里?

编辑:

谢谢回复人员。随着你的回答和一些跟进谷歌搜索我找到了我的困惑的来源。我假设程序只会真正使用堆栈的顶部变量,并逐个打开/关闭它们。

答案

你可能会误解某些东西。

实际上,堆栈将始终是顺序存储。但是,堆栈的大小将远远大于堆。虽然事物是从堆栈“弹出”的,但实际上这不适用于声明本地数组的函数。

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

另一答案

虽然抽象C语言没有说明如何分配本地对象(即没有明确引用“堆栈”语言规范),但本地对象的存储持续时间与堆栈的LIFO属性很好地对齐:本地对象以与以下相反的顺序销毁:他们的创作。最后创建的对象首先被销毁,反之亦然。

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

每个数组对象都是在堆栈顶部完整创建的。当数组对象到达其存储持续时间的末尾时,它就像“弹出顶部”一样,就像你说的那样。任何可能已经存在于堆栈上方的东西应该已经被那个时刻弹出。

另一答案

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

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

堆是一个动态内存池,您可以在需要时借用内存并将内存返回给它。所以,当你借用内存,即'malloc'时,你可以按照自己的意愿使用它,直到你返回(免费)它,这样它就可以被一个不同的程序重用。

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

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

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

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

以上是关于堆栈上的C数组的主要内容,如果未能解决你的问题,请参考以下文章

在进行 C 到 Intel x86 程序集转换时,堆栈上的数组分配占用的空间超过了所需的空间 [重复]

为啥 C++ 不支持堆栈上的动态数组? [关闭]

c_cpp 使用在堆栈上声明的数组(int myArray [3])和堆上的数组(int * myArray = new int [size]

从堆栈中弹出特定片段并删除其他片段

Android从后台堆栈中删除事务

Android - 从堆栈中间删除特定片段不起作用