声明一个数组中间函数是不好的做法

努力只想问我在这里真正想要的是什么…我真的只关心是否认为不好的做法或者不要在下面声明一个大小可能不同的数组。 如果是……我通常会使用malloc()代替。

void MyFunction() { int size; //do a bunch of stuff size = 10; //but could have been something else int array[size]; //do more stuff... } 

通常是的,这是不好的做法,尽管新标准允许您使用此语法。 在我看来,你必须在(在堆上)分配你想要使用的内存,并在完成后释放它。 由于没有可移植的方法来检查堆栈是否足以容纳该数组,因此您应该使用一些可以真正检查的方法 – 比如malloc / calloc&free。 在嵌入式世界中,堆栈大小可能是个问题。

如果您担心碎片,可以创建自己的内存分配器,但这是一个完全不同的故事。

那要看。 第一个显然不是我称之为“正确的”,第二个只是在相当有限的情况下。

在第一个中,你不应该在C中转换来自malloc的返回 – 这样做可以掩盖意外省略包含正确头文件( )的错误。

在第二种情况下,您将代码限制为C99或gcc扩展名。 只要你知道这一点,并且它适用于你的目的,它就可以了,但几乎没有我称之为便携性的理想。

至于你真正要问的是:上面提到的小错误是固定的,第一个是便携式的,但可能比你想要的慢。 如果第二个便携式足以满足您的需要,它通常会更快。

对于你的问题,我认为每个都有其优点和缺点。

动态分配:
慢,但是你可以通过检查指针来检测何时没有内存给你的程序员。

堆栈分配:
只有在C99中,它的速度非常快,但在stackoverflow的情况下,你运气不好。

总之,当您需要一个小型数组时,请将其保留在堆栈中。 否则,明智地使用动态内存。

反对VLA的论点运行,因为堆栈溢出的绝对不好,当您做足够的思考/检查以确保它们安全时,您已经做了足够的思考/检查以使用固定大小的数组:

1)为了安全地使用VLA,您必须知道有足够的堆栈可用。

2)在绝大多数情况下,你知道有足够堆栈的方式是你知道所需size的上限,并且你知道(或者至少愿意猜测或要求)堆栈的下限,一个小于另一个。 所以只需使用固定大小的数组。

3)绝大多数情况并非如此简单,你使用的是多个VLA(每次调用递归函数时可能只有一个),并且您知道它们的大小的上限,小于可用堆栈的下限。 因此,您可以使用固定大小的数组并根据需要将其分成多个部分。

4)如果你遇到其中一个案例,在malloc的表现不可接受的情况下,请告诉我……

从源代码的POV开始,使用VLA可能更方便。 例如,您可以使用sizeof (在定义范围内)而不是在变量中维护大小,并且将数组划分为块的业务可能需要传递额外的参数。 因此,有时候便利性会有一些微小的好处。

更容易错过你正在使用大量的堆栈,产生未定义的行为,如果不是一个相当可怕的int buf[1920*1024]int buf[MAX_IMG_SIZE]你有一个int buf[img->size] 。 这在第一次实际处理大图像时工作正常。 这通常是正确测试的问题,但如果您错过了一些可能的困难输入,那么它将不会是第一个或最后一个测试套件。 我发现一个固定大小的数组提醒我要么对输入进行固定大小的检查,要么用动态分配替换它,并且不要担心它是否适合堆栈。 没有有效的选择将它放在堆栈上, 不用担心它是否适合……

从UNIX / C的角度来看两点 –

当你强制它调用brk()时,malloc只会很慢。 合理数组的含义与为变量分配堆栈空间相同。 顺便说一句,当你使用方法#2(通过alloca和我见过的代码libc)时,也会调用brk()来查找大对象。 所以这是一个洗。 注意:对于#2和#1,您仍然必须直接或间接调用memset类型的调用来将数组中的字节归零。 这只是真实问题(IMO)的旁注:

真正的问题是内存泄漏。 当函数重新运行时,alloca会自行清理,因此#2不太可能导致问题。 使用malloc / calloc,您必须调用free()或开始泄漏。