gpt4 book ai didi

c - 可变长度数组和动态内存分配有什么区别?

转载 作者:行者123 更新时间:2023-12-04 02:26:18 25 4
gpt4 key购买 nike

int a[n];

对比

int * a;
a = malloc(n * sizeof(int));

谁能分别解释一下这两种方法的优缺点? (效率、安全等)

最佳答案

主要区别在于 VLA 声明引入了一种新的可变修改 (VM) 类型并且该对象具有自动存储,malloc() 变体具有动态存储。

代码:

int a[n];

被编译器视为:

int T_elems = n;
typedef int T[T_elems];
T a;

结果数组 a 具有自动存储,并且在现代系统上分配在堆栈上。自动意味着在离开范围时释放对象的内存,如果对象被引入。

int *b;
{
int a[n];
// `a` is valid
b = a;
}
// resources pointed by `b` are released

另一方面,第二个片段:

int * a = malloc(n * sizeof(int));

创建一个指向int 的指针并为其分配一个动态分配的对象。即使 a 的范围已经结束,对象资源仍然有效。内存在使用 free() 释放之前有效。

int *b;
{
int * a = malloc(n * sizeof(int));
b = a;
}
// resources pointed by `b` are valid!
free(b);
// memory is no longer valid

有一个常见的误解,认为 VLA 总是分配在堆栈上。可以通过指向数组的指针在堆上分配 VLA:

int (*a)[n] = malloc(sizeof(int[n]));

总结:

  1. VLA(和 VM 类型)

优点:

  • 自动 VLA 的简单分配
  • “总是”成功(C 标准未定义失败时的行为)
  • 分配非常快(比固定数组稍慢)
  • 自动 VLA 没有泄漏风险
  • 可以有动态存储(通过指向 VLA 的指针)
  • 对于多维数组非常方便
  • 携带其大小 sizeof a 返回 n * sizeof int

缺点:

  • 自动 VLA 很容易溢出堆栈
  • 不能在文件范围内定义 VM 类型(不能返回)
  • VM 类型不能用作结构成员
  • 自 C11 起成为可选功能
  • 计算 VLA 类型的 sizeof 的操作数
  • 不能调整自动 VLA 的大小
  1. 动态一维数组。

优点:

  • 受所有 C 标准支持
  • 可以是任意大小,没有堆叠限制
  • 指示分配是否成功,但是在现代操作系统 malloc() 上保留地址空间。操作系统很少保证内存 已保留
  • 可以用realloc()调整大小

缺点:

  • 更冗长的语法
  • 必须检查是否成功
  • 分配比任何基于堆栈的分配都慢
  • 必须使用free() 释放内存以避免泄漏
  • 不携带大小,必须保持数组的大小

组织成表格的相同数据:

<表类="s-表"><头><日> 自动 VLA malloc<正文>语法简单更详细错误行为堆栈溢出 错误处理不可能:失败时的行为未定义必须检查 malloc的返回值最大尺寸筹码量堆大小(大于堆栈)速度非常快(比固定数组稍慢)比任何基于堆栈的分配都慢解除分配自动;无泄漏风险必须使用 free() 释放内存以避免泄漏数组大小支持是的,通过 sizeof不行,程序员必须显式存储可以返回吗?没有是可以放入 struct吗?没有是便携性C99,自C11起成为可选特性所有C标准都支持支持缩放吗?没有是的,通过 realloc多维度语法简单可能会混淆语法

关于c - 可变长度数组和动态内存分配有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67356818/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com