【问题标题】:variable length arrays in C and initializing it in place [duplicate]C中的可变长度数组并将其初始化到位[重复]
【发布时间】:2013-09-22 03:40:56
【问题描述】:

C99 允许定义具有非常量大小的数组,即用于定义数组的大小可以在运行时更改。代码 sn-p 来解释它,

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 的值对于编译器是未知的。
  • 这不是提议的原始问题的副本。这些问题询问为什么不能初始化可变长度数组。这个问题专门询问为什么 C 标准不提供初始化可变长度数组。

标签: c arrays initialization


【解决方案1】:

这是因为编译器不知道用多少个零“填充”剩余元素。

声明

char arrA[3] = { 0 };

可以很容易地翻译成

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

在编译期间,而变长声明则不能。

由于 C 没有运行时系统,编译器必须根据给定的长度添加代码以动态填充零。 C 标准力求最小化并为程序员提供最大的权力,因此避免了这样的事情。从 C11 开始,可变长度数组已从标准中删除,并被标记为可选功能。

【讨论】:

  • 另外,如果length=0,就会出错。
  • 当然在编译时,编译器不知道还有多少剩余元素。但是这些信息在运行时确实存在,编译器可以生成代码来执行所需的初始化。那么为什么该标准没有对此做出规定呢?
  • 我在回答中添加了一些信息:)
【解决方案2】:

如果我们查看 C99 草案标准部分 6.7.8Initialization 段落 3 说,标准似乎不允许这样做(强调我的):

要初始化的实体的类型应该是一个未知大小的数组或一个对象类型 不是变长数组类型

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

【讨论】:

  • 这个问题似乎是在问为什么 C 1999 标准不支持可变长度数组的初始化。这个答案没有回答那个问题。
  • @EricPostpischil 嗯,我可以发誓它最初不是这样读的,但很可能我当时的解释不同......我会更新
【解决方案3】:

假设:C 是一种中级语言,标准委员会不希望在基本语言中包含执行未在编译时确定的工作量的操作(将库算作单独的)。

目前我想到的所有 C 的基本操作(也许有人会纠正我)只需要在编译时确定的工作量:调用一个函数,将两个数字相乘,将一个结构分配给另一个,以及很快。这些都可以通过在编译时执行的许多机器指令来执行。

即使为可变长度数组分配空间也只需要编译时的工作量:计算大小并从堆栈指针中减去它。相反,初始化所有这些空间需要在运行时确定的工作量。这不符合 C 语言的特点。

库例程可能需要在运行时确定的工作量,例如memset

【讨论】:

  • 有点道理,尽管 VLA 仍然使用未知(在编译时)数量的其他通常有限的资源(堆栈)。在允许之后,对未知数量的 CPU 周期大惊小怪并强迫程序员显式调用 memset(它可能在优化后生成相同的代码)似乎毫无意义。
  • +1 用于捕捉我们其他人错过的细节。
猜你喜欢
  • 2013-06-24
  • 2014-07-25
  • 1970-01-01
  • 1970-01-01
  • 2016-11-26
  • 2020-04-12
  • 2021-12-30
  • 2013-06-23
  • 1970-01-01
相关资源
最近更新 更多