在C语言中,可变长度数组的初始化方法

4

C99允许定义非常量大小的数组,即用于定义数组的大小可以在运行时更改。以下是一个代码片段来解释它:

void dummy_function1(unsigned int length) {

 char arrA[length];  //Allowed
 .
 .
}

然而,它不允许在原地初始化,即:
void dummy_function2(unsigned int length) {

 char arrA[length]={0}; //Not Allowed, compiler throws an error
 char arrB[10]={0};     //Allowed
 .
}

我不理解,为什么对于长度可变和长度固定的数组会有行为差异。在这两种情况下,当函数被调用时,都会给数组分配内存。

length 不是编译时常量。它将在运行时由用户输入。在编译时,编译器无法知道 length 的值。 - haccks
1
这不是提出的原始问题的重复。那些问题问为什么变长数组不能被初始化。这个问题特别询问C标准为什么不提供初始化变长数组。 - Eric Postpischil
3个回答

4
这是因为编译器不知道要用多少个0来“填充”其余的元素。
该语句:
char arrA[3] = { 0 };

可以轻松地翻译成

char arrA[3] = { 0, 0, 0 };

在编译时,静态数组的长度必须是常量,而变长数组则不需要。

C语言没有运行时系统,因此编译器必须添加代码来动态填充零,具体取决于给定的长度。C标准致力于最小化并赋予程序员最大的能力,因此避免了这类事情。从C11开始,变长数组已被从标准中删除,并被标记为可选功能。


1
此外,如果长度等于0,那将会是一个错误。 - nj-ath
1
当然,在编译时,编译器不知道剩余元素的数量。 但是这些信息在运行时存在,并且编译器可以生成代码来执行所需的初始化。那么为什么标准没有考虑这一点呢? - Eric Postpischil
我给我的回答添加了一些信息 :) - Johan Henriksson

4

从C99草案标准的第6.7.8节"Initialization"第3段来看,似乎不允许这样做(强调是我的):

要初始化的实体的类型必须是未知大小的数组或者不是变长数组类型的对象类型。

为什么不支持变长数组的初始化呢?很可能是因为支持变长数组的初始化需要在运行时进行不确定量的工作。


1
这个问题似乎在问为什么C 1999标准不支持可变长度数组的初始化。但是这个答案并没有回答那个问题。 - Eric Postpischil
@EricPostpischil 嗯,我本来以为它不是这样的,但很可能当时我只是有不同的理解... 我会更新。 - Shafik Yaghmour

2
假设:C语言是一种中级语言,标准委员会不想在基本语言中包含(将库视为单独的)执行编译时无法确定工作量的操作。
我目前能想到的所有C语言基本操作(也许有人会纠正我),都仅需要在编译时确定一个固定数量的机器指令来执行:调用函数、两个数字相乘、将一个结构体赋值给另一个结构体等等。
即使为变长数组分配空间,也仅需要在编译时确定一个工作量:计算大小并从堆栈指针中减去。相比之下,初始化所有这些空间则需要在运行时确定工作量。这与C语言的特点不符。
库例程可能需要在运行时确定工作量,例如memset

有点道理,虽然VLA仍然使用未知(在编译时)数量的其他资源(堆栈)。允许这样做之后,对于未知数量的CPU周期进行纠结,并强制程序员显式调用memset(在优化后可能生成相同的代码)似乎是毫无意义的。 - hyde
+1 意味着你捕捉到了我们忽略的细节。 - Shafik Yaghmour

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接