qdi*_*dii 11 c c++ c99 variable-length-array c++11
我从许多人那里听说,在C99中引入的可变长度阵列非常糟糕.IRC的一些人在一分钟之前说过"我不认为C++会得到VLA,而strousoup对他们做了一些非常负面的评论".
这些人讨厌VLA的原因是什么?
VLA在运行时在堆栈上分配数组,这使得在编译时使用堆栈大小变得更加困难甚至无法确定.由于堆栈具有相当少的可用内存(与堆相比),许多人担心VLA具有很大的堆栈溢出潜力.
即将推出的MISRA-C编码标准很可能也会禁用VLA.
虽然变长数组有自己的问题,我们应该记住他们是如何走过来的:作为一个替代alloca(),这可以说是甚至更成问题.
虽然在PDP-11上实现起来微不足道,但在其他架构上并非如此,Ritchie和Thompson 将其从实施中删除.
然而,可变大小的自动分配显然是有用的,alloca()尽管它存在问题但仍然可以复活(特别是,它不能用于任何可能进行任意函数调用的地方,并且在许多架构上它必须是内置的编译器).C工作组同意提供这样的功能,但认为可变长度阵列是优秀的解决方案.
如果你看一下C99中添加的功能(复数,类型通用数学,restrict......),你应该注意到它们中的很多都是为了让C成为更好的数值计算语言.可变长度数组在那里也很有用,我相信Fortran当时已经拥有它们.此外,它们的引入还导致可变修改的派生类型(例如指向可变大小的数组的指针),这在处理矩阵时特别有用.
正如其他人指出的那样,VLA 使堆栈帧溢出变得非常容易。我不是编译器编写者,但我的理解是 VLA 也可以成为支持的错误(它们现在在 C2011 中是可选的)。并且它们的使用仅限于块或函数范围;您不能在文件范围内使用 VLA,并且它们不能具有外部链接。
不过,我不希望看到 VLA 语法消失;当动态分配内部维度直到运行时才知道的多维数组时,它真的很方便,例如:
size_t r, c;
// get values for r and c
int (*arr)[c] = malloc(r * sizeof *arr);
if (arr)
{
...
arr[i][j] = ...;
...
free(arr);
}
Run Code Online (Sandbox Code Playgroud)
一个连续的分配(和一个相应free),并且我可以下标它作为一个2D阵列。替代方案通常意味着零碎分配:
size_t r, c;
...
int **arr = malloc(sizeof *arr * r);
if (arr)
{
for (i = 0; i < c; i++)
arr[i] = malloc(sizeof *arr[i] * c);
...
arr[i][j] = ...;
...
for (i = 0; i < c; i++)
free(arr[i]);
free(arr);
}
Run Code Online (Sandbox Code Playgroud)
或使用一维偏移:
int *arr = malloc(sizeof *arr * r * c);
if (arr)
{
...
arr[i * r + j] = ...;
...
free(arr);
}
Run Code Online (Sandbox Code Playgroud)