13

可能重复:
Malloc 或普通数组定义?

我们了解到 C 和动态变量中存在动态内存:

#include <stdio.h>
int a = 17;
int main(void)
{
  int b = 18; //automatic stack memory
  int * c;
  c = malloc( sizeof( int ) ); //dynamic heap memory
  *c = 19;
  printf("a = %d at address %x\n", a, &a);
  printf("b = %d at address %x\n", b, &b);
  printf("c = %d at address %x\n", *c, c);
  free(c);  
  system("PAUSE");  
  return 0;
}

我如何知道要使用哪种类型的内存?我什么时候需要一个或另一个?

4

6 回答 6

34

在以下情况下使用动态:

  1. 当你需要大量内存时。典型的堆栈大小是 1 MB,所以任何大于 50-100KB 的东西最好动态分配,否则你就有崩溃的风险。一些平台可以有这个限制甚至更低。

  2. 当函数返回后内存必须存在。函数结束时堆栈内存被破坏,动态内存在需要时被释放。

  3. 当您构建大小未知(即可能变大)的结构(如数组或图形)时,会动态变化或难以预先计算。动态分配允许您的代码在任何时候并且仅在您需要时自然地逐块请求内存。不可能在for循环中重复请求越来越多的堆栈空间。

否则首选堆栈分配。它更快并且不会泄漏。

于 2012-08-28T14:50:51.220 回答
5

当仅在运行时事先不知道分配的大小时,您可以使用动态内存。

例如,您要求用户输入名称(最多可以说 10 个名称)并将它们存储在字符串数组中。由于您不知道用户将提供多少名称(仅在运行时),因此只有在知道要分配多少名称后才必须分配数组,因此您将使用动态分配。

您当然可以使用固定大小的 10 数组,但是对于较大的数量,这将是浪费

于 2012-08-28T14:44:13.080 回答
3

如果您不确切知道程序在编译时需要分配多少内存,请使用动态内存分配

int a[n]例如将您的数组大小限制为 n。此外,无论您是否使用它,它都会分配 nx 4 字节的内存。这是在堆栈上分配的,并且变量 n必须在编译时已知。

int *a = (int *)malloc(n * sizeof (int))另一方面,在运行时分配,在堆上,并且n只需要在运行时知道,不一定在编译时知道。

这还可以确保您分配的内存与您真正需要的内存一样多。但是,当在运行时分配它时,必须由您使用free.

于 2012-08-28T14:44:45.130 回答
3

您应该在以下情况下使用动态内存:

  • 如果您希望您的对象在创建它的范围之外持续存在。
  • 通常,堆栈大小是有限的,因此如果您的对象占用大量内存,那么您可能会用完堆栈空间,在这种情况下,通常会进行动态内存分配。

请注意,c99 标准在 C 中引入了可变长度数组(VLA),因此您无需使用动态内存分配,因为您事先不知道数组尺寸(除非#2上面提到的是这种情况)

最好尽可能避免动态内存分配,因为这意味着显式管理内存,而不是语言提供的自动机制。显式内存管理意味着您容易犯更多错误,这可能会导致灾难性后果。
话虽如此,动态内存分配不能总是避免,必须在必须使用时使用(上面提到的两种情况)。

于 2012-08-28T14:46:51.093 回答
2

如果您可以在没有动态分配的情况下进行编程,请不要使用它!
但是有一天你会被阻塞,解除阻塞的唯一方法就是使用动态分配,然后你就可以使用它了

于 2012-08-28T14:50:14.953 回答
1

Als 提出了一个有趣的观点,即如果您的对象需要在创建它的范围之外持续存在,您应该从堆中分配内存。在上面的代码中,您根本不需要从堆中分配内存。你可以像这样重写它:

#include <stdio.h>
int a = 17;
int main(void)
{
    int b = 18; //automatic stack memory
    int c[1]; // allocating stack memory. sizeof(int) * 1
    c[0] = 19;
    printf("a = %d at address %x\n", a, &a);
    printf("b = %d at address %x\n", b, &b);
    printf("c = %d at address %x\n", c[0], c);
    system("PAUSE");  
    return 0;
}

事实上,作为 C99 标准(可变长度数组)的一部分,您可以使用[]运算符在堆栈上为数组分配动态空间,就像通常创建数组一样。您甚至不需要在编译时知道数组的大小。编译器只会x86根据请求的分配空间调整 esp 寄存器(对于机器),你就可以开始了。

于 2012-08-28T15:00:22.663 回答