在这个问题,有人建议意见,我应该不会投的结果malloc,即
int *sieve = malloc(sizeof(int) * length);
Run Code Online (Sandbox Code Playgroud)
而不是:
int *sieve = (int *) malloc(sizeof(int) * length);
Run Code Online (Sandbox Code Playgroud)
为什么会这样呢?
我理解变量长度数组是什么以及它们是如何实现的.这个问题是关于他们存在的原因.
我们知道VLA只允许在功能块(或原型)中使用,并且它们基本上不能在堆栈上的任何地方(假设正常实现):C11,6.7.6.2-2:
如果标识符被声明为具有可变修改类型,则它应该是普通标识符(如6.2.3中所定义),没有链接,并且具有块范围或函数原型范围.如果标识符被声明为具有静态或线程存储持续时间的对象,则它不应具有可变长度数组类型.
我们举一个小例子:
void f(int n)
{
int array[n];
/* etc */
}
Run Code Online (Sandbox Code Playgroud)
有两种情况需要注意:
n <= 0:f必须防范这一点,否则行为是不明确的:C11,6.7.6.2-5(强调我的):
如果size是一个不是整数常量表达式的表达式:如果它出现在函数原型范围的声明中,则将其视为替换为
*; 否则, 每次评估它时,其值应大于零.可变长度数组类型的每个实例的大小在其生命周期中不会改变.如果size表达式是运算sizeof符操作数的一部分,并且更改size表达式的值不会影响运算符的结果,则无法指定是否计算size表达式.
n > stack_space_left / element_size:没有标准的方法可以找到剩余多少堆栈空间(因为只要涉及标准就没有堆栈这样的东西).所以这个测试是不可能的.只有明智的解决方案才是拥有预定义的最大可能大小n,例如N,确保不会发生堆栈溢出.
换句话说,程序员必须确保0 < n <= N一些N选择.但是,程序应该n == N仍然可以工作,所以人们也可以声明数组的大小N是常量而不是可变长度n.
我知道引入了VLA以替换alloca(在本回答中也提到过),但实际上它们是相同的(在堆栈上分配可变大小的内存).
所以问题是为什么allocaVLA存在并且因此VLA存在以及它们为什么不被弃用?在我看来,使用VLA的唯一安全方法是使用有限大小,在这种情况下,采用具有最大大小的正常阵列始终是可行的解决方案.