Tim*_*Tim 46 c arrays variable-length-array
使用可变长度数组有一些开销吗?可以在运行时通过命令行参数传递数组的大小吗?与自动和动态分配数组相比,为什么会引入它?
AnT*_*AnT 43
VLA确实有一些开销(与"普通"命名的编译时大小的数组相比).
首先,它具有运行时长度,但语言为您提供了在运行时(使用sizeof)获取数组实际大小的方法.这立即意味着数组的实际大小必须存储在某处.这导致一些无关紧要的每阵列内存开销.但是,由于VLA只能被声明为自动对象,因此这种内存开销并不是任何人都会注意到的.这就像声明一个整数类型的额外局部变量.
其次,VLA通常在堆栈上分配,但由于其可变大小,一般情况下,它在内存中的确切位置在编译时是未知的.因此,底层实现通常必须将其实现为指向内存块的指针.这引入了一些额外的内存开销(对于指针),由于上述原因,这又是完全无关紧要的.这也会带来轻微的性能开销,因为我们必须读取指针值才能找到实际的数组.这与访问malloc-ed数组时获得的开销相同(并且不会使用命名的编译时大小的数组).
由于VLA的大小是运行时整数值,因此它当然可以作为命令行参数传递.VLA并不关心它的大小来自哪里.
VLA是作为运行时大小的阵列引入的,具有低分配/解除分配成本.它们适合"普通"命名的编译时大小的数组(几乎没有分配 - 解除分配成本,但是固定大小)和malloc-ed数组(具有运行时大小,但分配 - 释放成本相对较高).
VLA遵循[几乎]与自动(即本地)对象相同的与范围相关的生命周期规则,这意味着在一般情况下它们不能替换malloc-ed数组.它们的适用性仅限于需要具有典型自动生命周期的快速运行时大小的阵列的情况.
Jon*_*ler 28
使用可变长度数组会有一些运行时开销,但您必须非常努力地测量它.请注意,sizeof(vla)如果vla是可变长度数组,则不是编译时常量.
数组的大小可以在运行时传递给函数.如果您选择从命令行参数获取大小并将其转换为整数并在运行时将其传递给函数,那么就可以了 - 它会起作用.
使用可变长度数组是因为变量会自动分配到正确的大小,并在退出函数时自动释放.这样可以避免过度分配空间(当您使用最小的大小时,为最大可能的大小分配足够的空间),并避免内存清理问题.
此外,对于多维数组,AFAIK的行为更像Fortran - 您可以动态配置所有维度,而不是固定大小除了阵列的主要维度之外的所有维度.
VLA的一些运行时开销的具体证据 - 至少在SPARC(Solaris 10)上使用GCC 4.4.2.
考虑以下两个文件:
#include <assert.h>
#include <stddef.h>
extern size_t identity_matrix(int n, int m);
size_t identity_matrix(int n, int m)
{
int vla[n][m];
int i, j;
assert(n > 0 && n <= 32);
assert(m > 0 && m <= 32);
for (i = 0; i < n; i++)
{
for (j = 0; j < m; j++)
{
vla[i][j] = 0;
}
vla[i][i] = 1;
}
return(sizeof(vla));
}
Run Code Online (Sandbox Code Playgroud)
#include <assert.h>
#include <stddef.h>
extern size_t identity_matrix(int n, int m);
size_t identity_matrix(int n, int m)
{
int fla[32][32];
int i, j;
assert(n > 0 && n <= 32);
assert(m > 0 && m <= 32);
for (i = 0; i < n; i++)
{
for (j = 0; j < m; j++)
{
fla[i][j] = 0;
}
fla[i][i] = 1;
}
return(sizeof(fla));
}
Run Code Online (Sandbox Code Playgroud)
为了进行比较,本地数组的名称是不同的(vlavs fla),并且在声明时数组上的维度是不同的 - 否则,文件是相同的.
我编译使用:
$ gcc -O2 -c -std=c99 fla.c vla.c
Run Code Online (Sandbox Code Playgroud)
目标文件大小有些不同 - 由"ls"和"size"测量:
$ ls -l fla.o vla.o
-rw-r--r-- 1 jleffler rd 1036 Jan 9 12:13 fla.o
-rw-r--r-- 1 jleffler rd 1176 Jan 9 12:13 vla.o
$ size fla.o vla.o
fla.o: 530 + 0 + 0 = 530
vla.o: 670 + 0 + 0 = 670
Run Code Online (Sandbox Code Playgroud)
我没有做过大量的测试,看看有多少开销是固定的,多少是可变的,但是使用VLA会有开销.