这本质上是我的问题。在函数的生命周期中,我生成一些整数,然后在算法中使用整数数组,该算法也是同一函数的一部分。整数数组只会在函数内使用,因此将数组存储在堆栈上自然是有意义的。
问题是在我完成生成所有整数之前我不知道数组的大小。
我知道如何在堆栈上分配固定大小和可变大小的数组。但是,我不知道如何在堆栈上增长数组,这似乎是解决我的问题的最佳方法。我相当确定这可以在汇编中完成,您只需递增堆栈指针并为每个生成的 int 存储一个 int,因此 int 数组将位于堆栈帧的末尾。这可能在C中做到吗?
这本质上是我的问题。在函数的生命周期中,我生成一些整数,然后在算法中使用整数数组,该算法也是同一函数的一部分。整数数组只会在函数内使用,因此将数组存储在堆栈上自然是有意义的。
问题是在我完成生成所有整数之前我不知道数组的大小。
我知道如何在堆栈上分配固定大小和可变大小的数组。但是,我不知道如何在堆栈上增长数组,这似乎是解决我的问题的最佳方法。我相当确定这可以在汇编中完成,您只需递增堆栈指针并为每个生成的 int 存储一个 int,因此 int 数组将位于堆栈帧的末尾。这可能在C中做到吗?
我不同意您的断言,即“将数组存储在堆栈上自然是有意义的”。当您在编译时知道大小时,堆栈内存实际上是为您设计的。我认为动态内存是通往这里的路
C没有定义“堆栈”是什么。它只有静态、自动和动态分配。静态和自动分配由编译器处理,只有动态分配将控制权交到您手中。因此,如果要手动释放对象并分配更大的对象,则必须使用动态分配。
不要在堆栈上使用动态数组(比较为什么使用 alloca() 不被认为是好的做法?),更好地从堆中分配内存malloc
并使用realloc
.
从不使用 alloca()
恕我直言,这一点在标准参考文献中做得不够好。
一条经验法则是:
如果您不准备将最大可能大小静态分配为固定长度的 C 数组,那么您也不应该动态地分配
alloca()
。
为什么?您试图避免的原因malloc()
是性能。
alloca()
会变慢,并且在任何情况下都不起作用静态分配将失败。它通常不太可能成功malloc()
。
一件事是肯定的。静态分配最大值将超过malloc()
和alloca()
。静态分配通常非常接近无操作。无论如何,大多数系统都会为函数调用提前堆栈指针。多远没有明显区别。
所以你告诉我的是你关心性能但想阻止一个无操作的解决方案?想想你为什么会有这种感觉。
压倒性的可能性是您担心分配的大小。
但正如解释的那样,它是免费的,它会被收回。有什么烦恼?如果担心“我没有最大值或不知道它是否会溢出堆栈”,那么您不应该使用alloca()
,因为您没有最大值并且知道它是否会溢出堆栈。
如果您确实有最大值并且知道它不会破坏堆栈,那么静态分配最大值并回家。这是免费午餐——记得吗?
这alloca()
要么是错误的,要么是次优的。
每次使用时,alloca()
您要么是在浪费时间,要么是在一个难以测试的任意缩放天花板中编码,该天花板静静地睡着,直到事情真的很重要,然后才搞砸了某人的一天。
不。
PS:如果您需要一个大的“工作空间”,但malloc()
/free()
开销是一个瓶颈,例如在一个大循环中重复调用,那么考虑在循环之外分配工作空间并将其从迭代带到迭代。如果您发现“大”情况,您可能需要重新分配工作空间,但通常可以将分配数量除以 100 甚至 1000。
脚注:
必须有一些理论算法,其中 a() 调用 b() 并且如果 a() 需要大量环境 b() 则不需要,反之亦然。在那种情况下,可能会出现某种怪异的附加赛,其中堆栈溢出被alloca()
. 我从未听说过或见过这样的算法。合理的标本将不胜感激!
为了解决您的问题,动态内存分配看起来很理想。
int *a = malloc(sizeof(int));
并取消引用它以存储 value 。每次需要将一个新整数添加到现有整数列表中
int *temp = realloc(a,sizeof(int) * (n+1)); /* n = number of new elements */
if(temp != NULL)
a = temp;
一旦完成使用此内存free()
它。
C 编译器的内部要求堆栈大小在编译时是固定的或可计算的。自从我使用 C(现在是 C++ 转换)以来已经有一段时间了,我不知道这是为什么。http://gribblelab.org/CBootcamp/7_Memory_Stack_vs_Heap.html对两种方法的优缺点进行了有用的比较。
我很欣赏你的汇编代码类比,但如果这有意义的话,C 很大程度上是由操作系统管理的,它强加/提供任务、进程和堆栈符号。