了解处理可变长度数据,特别关注 C(99) 中的可变长度数组

Understanding the handling Variable-Length Data with special focus on variable length arrays in C(99)

以下是红龙书的节选。处理程序激活记录中变长数据项的处理。

Pascal is almost unique among languages in requiring that arrays local to a procedure have a length that can be determined at compile time. More often, the size of a local array may depend on the value of a parameter passed to the procedure. In that case, the size of all the data local to the procedure cannot be determined until the procedure is called.

A common strategy for handling variable-length data is suggested in Fig. 7.15, where procedure p has three local arrays. The storage for these arrays is not part of the activation record for p; only a pointer to the beginning of each array appears in the activation record. The relative addresses of these pointers are known at compile time, so the target code can access array elements through the pointers.

Also shown in Fig. 7.15 is a procedure q called by p. The activation record for q begins after the arrays of p, and the variable-length arrays of q begin beyond that.

在上面摘录的第一部分中,文本讨论了 Pascal 编程语言的特性,然后他们讨论了相同的可能实现。现在我不熟悉 Pascal 并且想了解 C.

中处理情况的方式

我知道可以使用 malloc 及其姐妹函数在 C 中动态创建数组,这会导致在堆上分配内存并将指向第一个字节的指针返回给我们.完全不是问题。

如果我们在 C 中创建数组,其中数组的大小是常量,如:

int function() {
   int a[100];
  }

然后将数组放在激活记录的local data部分如下所示:

在上面的例子中,数组a的大小在编译时是已知的。没问题。

现在的情况:“更常见的是,局部数组的大小可能取决于传递给过程的参数值。在这种情况下,所有本地数据的大小都取决于在调用过程之前无法确定过程。"

案例一:

现在让我们考虑下面的代码:

  int function(int n){
           int a[n];
  }
  int main() {
        function(10);
  }

现在在上面的情况下,参数 nfunction 的大小可以在编译时知道,因此数组的大小 a 虽然可以知道变量在编译时。按照这个逻辑C是不是按照龙书fig 7.15中的方式分配了上面的数组a

案例二:

  int function(int n){
           int a[n];
  }
  int main() {
        int x;
        scanf("%d",&x);
        function(x);
  }

现在在上面的情况下,参数nfunction的大小只能在运行时知道(?)还是情况如上,即在编译时已知 ? 现在在这段代码中,数组 a 分配在哪里。堆还是栈?

我去了 here, and here 但没有找到我要找的解释...


这里我说的是C99

通常,C 实现在堆栈上分配 VLA,而不是在单独的堆数据结构中,但这实际上不是标准所要求的。由于 VLA 的大小仅在运行时已知,这意味着您将获得此类函数的可变大小激活记录。激活记录如何分配和布置的细节往往取决于目标机器及其 ABI,因此尝试将其分解(如上图所示)对于不同的编译器和体系结构将有很大不同。