编译器如何在不知道编译时大小的情况下分配内存?

拉胡尔:

我编写了一个C程序,该程序接受来自用户的整数输入,用作整数数组的大小,并使用该值声明给定大小的数组,并通过检查数组的大小来确认它。

码:

#include <stdio.h>
int main(int argc, char const *argv[])
{
    int n;
    scanf("%d",&n);
    int k[n];
    printf("%ld",sizeof(k));
    return 0;
}

令人惊讶的是,这是正确的!该程序能够创建所需大小的数组。
但是所有静态内存分配都是在编译时完成的,并且在编译时n不知道的值,那么编译器怎么能分配所需大小的内存呢?

如果我们可以像这样分配所需的内存,那么使用malloc()进行动态分配的用途是calloc()什么?

安特:

这不是“静态内存分配”。您的数组k是可变长度数组(VLA),这意味着该数组的内存在运行时分配。大小将由的运行时值确定n

语言规范没有规定任何特定的分配机制,但是在典型的实现中,您k通常最终将得到一个简单的int *指针,并在运行时将实际的内存块分配到堆栈上。

对于VLA sizeof运算符,还需要在运行时对其进行评估,这就是为什么您在实验中从中获得正确值的原因。只需使用%zu(而非%ld)来打印type的值size_t

malloc(和其他动态内存分配功能)的主要目的是覆盖适用于本地对象的基于范围的生存期规则。即分配给内存的内存将malloc“永远”分配,或者直到您用显式取消分配内存为止free分配malloc有的内存不会在块末自动释放。

在您的示例中,VLA不提供此“破坏范围”功能。您的数组k仍然遵守常规的基于作用域的生存期规则:其生存期在块的末尾结束。因此,在一般情况下,VLA无法替换malloc其他动态内存分配功能。

但是在特定情况下,当您不需要“破坏作用域”而只malloc需要分配运行时大小的数组时,VLA确实可以被视为替代malloc再次请记住,VLA通常是在堆栈上分配的,到目前为止,在堆栈上分配大块内存仍然是一个相当可疑的编程实践。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何在编译器不知道的情况下更改变量的值?

在不知道函数代码中其性质的情况下分配数组或整数(但编译器知道)

如何在golang编译时不知道protobuf3消息类型的情况下解析它?

如何在不知道大小的情况下取消分配不规则的***矩阵?

我可以在编译时不知道大小的情况下在堆栈上分配`std :: array`吗?

C ++ / g ++:在这种情况下,编译器如何处理内存分配?

在编译时不知道密钥的情况下解码JSON值

如何在编译时不知道其子类型的情况下将存储为对象的DbSet <T>拆包?

如何在不知道原始数组大小的情况下增加动态数组(C ++)的大小?

c语言如何在不知道大小的情况下创建数组

如何在不知道数组大小的情况下初始化数组?

如何在不知道大小的情况下绘制matlab中的所有矩阵元素?

如何在不知道数组大小的情况下复制二维数组

我可以在编译时不知道websharper模板名称的情况下填充它吗

在编译和处理ObjectDisposedException时不知道其System.Type的情况下打开新Form

Intellij Typescript 编译器不知道 TResult 类型

在不知道Main方法在哪里的情况下编译并执行Java源代码?

Net Core通用存储库模式如何在编译时不知道其类型的情况下注入DbContext?

在不知道大小的情况下寻找图标

在不知道数组大小的情况下输入数组

如何在不知道快捷键映射到的情况下取消分配快捷键

如何在不知道 JavaScript 中的 id/class/tag 的情况下分配给 HTML 元素?

如何在不知道其大小且无需多次读取的情况下从文件加载矩阵?

如何在不知道小部件的字体系列/大小的情况下更改小部件的字体样式?

Powershell:如何在不知道子网大小的情况下扫描局域网

如何在不知道挂载点的情况下知道设备UUID已挂载?

编译器如何在不更改参数列表的情况下重载模板函数?

如何在不得到编译器警告的情况下初始化char * args []

如何在没有 webpack fable-loader 的情况下使用 Fable 编译器?