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

标签 c arrays memory c99 variable-length-array

我编写了一个 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)来打印 size_t 类型的值。

malloc(和其他动态内存分配函数)的主要目的是覆盖适用于本地对象的基于范围的生命周期规则。 IE。使用 malloc 分配的内存“永远”分配,或者直到您使用 free 显式释放它。 malloc 分配的内存不会在 block 结束时自动释放。

在您的示例中,VLA 不提供这种“破坏范围”功能。您的数组 k 仍然遵守常规的基于范围的生命周期规则:它的生命周期在 block 的末尾结束。因此,一般情况下,VLA不可能替代malloc等动态内存分配函数。

但在特定情况下,当您不需要“击败作用域”而只需使用 malloc 来分配运行时大小的数组时,VLA 确实可能被视为 的替代品malloc。请再次记住,VLA 通常是在堆栈上分配的,直到今天在堆栈上分配大块内存仍然是一种相当有问题的编程实践。

关于c - 编译器如何在编译时不知道大小的情况下分配内存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46387111/

相关文章:

c - 为什么 UINT_MAX 返回 -1?

c - 在windows下查找程序在c中使用的总内存

c - 关于形式参数中 C 结构数组的错误

使用 make 编译时,main 的类型与先前的 main 定义发生冲突

c - 整数从字符串[]接收到错误的值

java - 如何从 Java IntStream 中的嵌套 .forEach 收集结果

Linux下造成内存泄漏

c - 从注册表启动程序与从启动文件夹启动的区别

java - foob​​ar 僵尸感染挑战

java - 格式化数组中的日期