微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

了解处理变长数据,特别关注 C(99)

如何解决了解处理变长数据,特别关注 C(99)

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

Pascal 在要求过程本地数组的长度可以在编译时确定的语言中几乎是独一无二的。更常见的是,本地数组的大小可能取决于传递给过程的参数的值。在这种情况下,在调用该过程之前无法确定该过程本地的所有数据的大小。

图 7.15 建议了一种处理可变长度数据的常用策略,其中过程 p 具有三个局部数组。这些阵列的存储不是 p 的激活记录的一部分;只有一个指向每个数组开头的指针出现在活动记录中。这些指针的相对地址在编译时是已知的,因此目标代码可以通过指针访问数组元素。

Figure

图 7.15 中还显示一个q 调用的过程 pq 的活动记录在 p 的数组之后开始,q 的变长数组在此之后开始。

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

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

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

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

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

activation record

在上面的例子中,数组 a 的大小在编译时就知道了。没有问题。

现在的情况:“更多情况下,本地数组的大小可能取决于传递给过程的参数的值。在这种情况下,无法确定过程本地的所有数据的大小直到调用该过程。”

案例 1:

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

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

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

情况 2:

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

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

我去了 hereherehere 但没有找到我要找的解释...


这里我说的是 C99

解决方法

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。