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

标签 arrays compiler-construction c99 variable-length-array runtime-environment

以下是 Compilers: Principles, Techniques, and Tools 的摘录。它涉及过程激活记录中可变长度数据项的处理。

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.

Figure

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];
}

然后该数组被放置在激活记录的本地数据部分,如下所示:

Activation record

在上面的示例中,数组a的大小在编译时就已知。这没有任何问题。

现在的情况:

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.

情况1:

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

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

int main() {
    function(10);
}

现在在上面的情况下,函数参数n的大小可以在编译时知道,因此数组a的大小虽然可以是变量在编译时已知。按照这个逻辑,C 是否按照龙书图7.15所示的方式分配上面的数组a

情况2:

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

int main() {
    int x;
    scanf("%d", &x);
    function(x);
}

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

我去了here , herehere ,但我没有找到我正在寻找的解释...


这里我说的是C99 .

最佳答案

一般来说,C 实现分配 VLAs在堆栈上,而不是在单独的堆数据结构中,但这实际上并不是标准所要求的。

由于 VLA 的大小仅在运行时已知,这意味着您将获得此类函数的可变大小的激活记录。激活记录如何分配和布局的细节往往取决于目标机器及其 ABI ,因此尝试将其分解(如上面的图表所示)对于不同的编译器和体系结构来说将是非常不同的。

关于arrays - 了解处理可变长度数据,特别关注 C(99) 中的可变长度数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66891948/

相关文章:

inheritance - 我们是否需要检查循环的单继承语言的继承图?

c# - 为什么添加局部变量会使 .NET 代码变慢

python - PyPy/RPython 可以用来生成一个小的独立可执行文件吗?

声明不完整的 C 函数

c - 分配给作为结构成员的指针会导致段错误

arrays - 无法将数组声明为公共(public) VBA

python - 我应该如何在 Python 中注释返回 ctypes 数组的函数?

javascript - 按数组中的特定字段对数组 (JavaScript) 进行排序

将十六进制 C 数组转换为 Matlab vector

c - 为什么很少有符合C99的编译器?