我编写了一个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;
}

令人惊讶的是,它是正确的!该程序能够创建所需大小的array.
但是所有的静电内存分配都是在编译时完成的,而在编译时n值是未知的,那么为什么编译器能够分配所需大小的内存呢?

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

推荐答案

这不是"静电内存分配".您的数组k是一个可变长度数组(VLA),这意味着此数组的内存是在运行时分配的.大小将由运行时值n确定.

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

对于VLAsizeof运算符,也会在运行时进行计算,这就是为什么您在实验中会从中获得正确的值.只需使用%zu(而不是%ld)打印类型size_t的值.

malloc(以及其他动态内存分配函数)的主要目的是覆盖适用于本地对象的基于作用域的生存期规则.也就是说,分配给malloc的内存仍然是"永远"分配的,或者直到您显式地将其分配给free.分配了malloc的内存不会在块的末尾自动释放.

与您的示例一样,VLA不提供这种" destruct 作用域"功能.您的数组仍然遵循常规的基于作用域的生存期规则:它的生存期在挡路结束时结束.因此,在一般情况下,VLA不可能取代malloc和其他动态存储器分配功能.

但在特定情况下,当您不需要"击败范围",只需要使用malloc来分配一个运行时大小的数组时,VLA可能确实会被视为malloc的替代品.请记住,VLA通常是在堆栈上分配的,到今天为止,在堆栈上分配大块内存仍然是一个相当有问题的编程实践.

C++相关问答推荐

想了解 struct 指针和空指针转换

strftime函数中%s的历史意义是什么?为什么没有记录?

为什么在Linux(特别是Ubuntu 20.04LTS)上,POSIX共享内存对象在重启后仍然存在,然后突然变成了根用户?

正在try 将文件/文件夹名从目录 struct 存储到链接列表

如何在C宏中确定 struct 中元素的类型?

在列表中插入Int指针(C)

如何捕捉只有换行符或空格字符缓冲区的边缘大小写

在C++中访问双指针

在创建动态泛型数组时,通过realloc对故障进行分段

C I/O:在Windows控制台上处理键盘输入

为四维数组中的Dim-1和Dim-3重新分配空间

如何在不读取整个字符串的情况下删除UTF8字符串的尾随空格以提高性能?

Linux分段故障(核心转储)

&stdbool.h&q;在嵌入式系统中的使用

通过GTK';传递回调参数;s g_signal_connect()导致C中出现意外值

一元运算符

为什么需要struct in_addr

在 C23 之前如何对空指针使用nullptr?

我们可以在不违反标准的情况下向标准函数声明添加属性吗?

如何使 clangd 启用仅标头库实现