【问题标题】:Why variable length arrays need to be declared at auto storage class?为什么需要在自动存储类中声明变长数组?
【发布时间】:2015-09-04 14:21:16
【问题描述】:

我在一些书籍中读到,用于声明可变长度数组的变量必须具有自动存储类。

谁能解释一下为什么它需要带有自动存储类的变量?

可变长度数组的空间是在栈还是堆中分配的?

【问题讨论】:

  • 能否给出书名及相关摘录
  • VLA 仅在堆栈上分配在本地范围内,因此在超出范围时会自动释放。差不多就这些了。
  • 您还会把 VLA 放在哪里?当 stack-VLA 不可用或数组需要超过分配它的函数时,动态分配数组是一种替代方法。
  • @Anony-mouse 我在 stepehen prata C prime plus book 中读到过

标签: c arrays stack heap-memory


【解决方案1】:

Rationale for International Standard—Programming Languages—C 对此进行了介绍,上面写着:

所有可变修改的类型必须在块范围或函数原型范围内声明。 文件范围标识符不能用可变修改类型声明。此外,数组 用 static 或 extern 存储类说明符声明的对象不能用可变长度数组类型声明 [...]

和:

将可变长度数组声明符限制为标识符 自动存储持续时间是自然的,因为文件中的“可变性” 范围需要一些参数化类型的概念。有 允许对结构成员进行可变修改的情绪; 但是允许结构成员具有可变长度数组 类型引入了一系列问题,例如通过时的处理 这些对象,甚至指向这些对象的指针,作为参数。在 此外,offsetof 宏的语义需要是 添加了扩展和运行时语义。最后出现了分歧 是否可以确定可变长度数组成员的大小 使用其他成员之一。委员会决定限制 可变长度数组类型到结构外部的声明和 工会。

【讨论】:

  • 你能解释一下这些问题吗??
  • 这个答案是错误的。理由只是说variable modified types 的对象只能被声明为具有自动存储。这意味着它们只能在函数体中定义,不能在全局范围内或作为结构成员或static 定义。对象可以是 VLA、指向 VLA 的指针、VLA 数组等。指向 VLA 的指针可以让您动态创建 VLA 对象
  • @AndrewFlemming 如果您允许static size_t n=42; static int arr[n];,一个明显的问题是静态初始化顺序。在调用 main() 之前初始化静态存储持续时间对象。在此示例中,n 将转到.dataarr 上的.bss。然后您必须考虑每个段中的单独初始化顺序以及.data.bss 之间的顺序。在不知不觉中,您已经发明了一些脑残且不必要的复杂事物,例如 C++ 中可怕的初始化规则。
  • @tstanisl 我不会说错的。 C 声明了以下声明数组的规则,6.7.6.2:“如果一个标识符被声明为具有可变修改类型,它应该是一个普通标识符(如 6.2.3 中所定义),没有链接,并且有任何一个块范围或函数原型范围。如果将标识符声明为具有静态或线程存储持续时间的对象,则它不应具有可变长度数组类型。这意味着您不能声明具有静态存储持续时间的 VLA。但是,是的,您也可以使用分配的存储持续时间来声明它们。
【解决方案2】:

这是错误的。 VLA 不必具有自动存储功能。 您可以创建一个指向 VLA 的指针并动态分配它。

int size = 42;
// automatic VLA
int A[size];
// dynamic VLA
int (*pA)[size] = malloc(sizeof *pA);

【讨论】:

  • 宁可:int* pA = malloc( sizeof(int[size]) ); 获取指向第一个元素的指针。指向 VLA 的数组指针使用起来很麻烦,因为您必须使用 (*pA)[i] = ... 而不是 pA[i] = ...
  • @Lundin,我同意动态 1D VLA 很麻烦,但它确实适用于多维数组。例如,(N,M,K) 形状的 3D VLA 可以创建为int (*A)[M][K] = malloc(N * sizeof *A); 并通过A[i][j][k] 访问
  • 你正在向合唱团布道 :) 见Correctly allocating multi-dimensional arrays
猜你喜欢
  • 2021-01-08
  • 2012-04-05
  • 2012-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-22
  • 2019-03-19
  • 1970-01-01
相关资源
最近更新 更多