c语言 - VLA 和通过 malloc 进行动态内存分配有什么区别?



我对此很好奇:

两者

之间的区别是什么:

const int MAX_BUF = 1000;
char* Buffer = malloc(MAX_BUF);

和:

char Buffer[MAX_BUF];
  • 案例 1:在

     char Buffer[MAX_BUF];
    

    Buffer 是一个大小MAX_BUF数组。分配技术称为 VLA。

  • 案例 2:在

    const int MAX_BUF = 1000;
    char* Buffer = malloc(MAX_BUF);
    

    Buffer是一个指针,它分配了一个大小为 MAX_BUF

  • 的内存,该内存1000

而且,数组与指针不同,C-FAQ 有一个非常好的集合详细说明了原因。

在可用性和行为方面的主要区别是:

  1. (1( 在堆栈上,通常是 Note,而 (2( 总是在堆上。
  2. (
  3. 1(分配后具有固定大小,(2(可以调整大小。
  4. (1( 在调用封闭函数并具有块范围 OTOH 时分配,(2( 在运行时动态分配内存,返回的内存具有从分配到释放的生命周期。
  5. (
  6. 1(分配的内存不需要由程序员管理,而在(2(中,所有malloc() d内存都应该free() d。

注:维基

例如,GNU C 编译器为堆栈上的 VLA 分配内存。

除了其他人所说的之外,我还会在内存管理方面添加一些信息。

1(主要区别在这里:

const int MAX_BUF = 1000;
char* Buffer = malloc(MAX_BUF);

您需要手动管理分配的内存,例如,使用完后Buffer释放内存。忘记free它(或释放它两次(可能会导致麻烦。

2(对于第二种情况:

char Buffer[MAX_BUF];

您不需要释放任何东西。它会自动被销毁。因此,您可以避免处理内存的任务 - 这很好。您应该尝试始终评估您需要哪种方法。

几点。

  • 由于第二个是在堆栈上分配的,因此当需要创建大型数组时,也会采用第一种方法 - 因为堆上通常有更多的内存可用。
  • 此外,如果您使用第二种方法创建数组,例如在方法中,对象的生命周期将是该方法 - 您将无法在该方法之外使用该数组。而动态分配则不是这样。
char* Buffer = malloc(MAX_BUF);

创建一个char指针Buffer,通过malloc动态分配MAX_BUF字节的内存,并使Buffer指向分配空间的开头。此内存在堆上分配。

char Buffer[MAX_BUF];

创建一个大小为 MAX_BUF 的数组Buffer,最多可容纳 MAX_BUF 个字符。请注意,您正在创建一个可变长度数组(C99 中引入的功能(,因为MAX_BUF是一个变量。可以在堆栈上创建此数组。

最显着的区别是范围。VLA 数组仅在声明它的范围内有效,而动态数组将在程序中的任何位置可用,直到您调用 free()

实际上,VLA 可能比动态内存快,以防编译器对 VLA 使用堆栈分配。但是,分配VLA的C标准没有指定。

(理论上,编译器可以在堆上分配VLA,但编译器也将负责清理。我认为不存在任何这样的解决方案。我使用过的每个编译器总是在堆栈上声明 VLA。

这意味着 VLA 不适合保存大量数据:您可能会面临堆栈溢出的风险。但是,当您使用动态内存时,这不是问题。

VLA 不具有与动态数组相同的可移植性,因为非常旧的编译器不支持 VLA。从理论上讲,新的 C11 编译器也不必支持 VLA,尽管在这一点上,我知道没有编译器愚蠢到放弃这种支持。


比较/总结:

  • 当本地数据量较少时,应使用 VLA,因为它们具有快速分配时间和自动清理功能。
  • 当有大量数据时,应使用动态数组,以防止堆栈溢出。
  • 当数据需要在函数执行后持久化并在程序的其他位置可用时,应使用动态数组。
  • 当您有特殊和/或不合理的可移植性要求时,应使用动态数组。

相关内容

  • 没有找到相关文章

最新更新