我编写了一个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 *指针,实际内存块在运行时分配到堆栈上.

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

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

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

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

C++相关问答推荐

无法删除C中文件夹内的文件

如何获得 C 函数的基本编译二进制代码?

引用如何出现在可从 C 代码调用的函数的签名中?

预处理器算法是否应该与编译所针对的体系结构相匹配?

C unsigned long 与转换未正确添加

在数组中查找与数组均值相同的对

如何使用带有 typedef 的注册存储类?

打印函数指针时不兼容的指针类型警告

在 C 中浮点到二进制

如何让我的应用程序找到 gettext 翻译?

OpenSSL 3 Diffie-Hellman 密钥交换 C++

char 数组是否保证为空终止?

是否允许 C 编译器合并对 volatile 变量的顺序赋值?

为什么有 i++;一世 - ;紧随其后?

项目中包含程序集文件时,来自 mmap 的意外 exec 权限

在 C/C++ 中获得正模的最快方法

C语言中i++和(i)++的区别

为什么为位字段分配值不返回相同的值?

使用无符号而不是有符号的 int 是否更有可能导致错误?为什么?

使用指向过去的 malloc 的指针是否定义明确?