c-我什么时候需要动态内存



可能重复:
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 %xn", a, &a);
  printf("b = %d at address %xn", b, &b);
  printf("c = %d at address %xn", *c, c);
  free(c);  
  system("PAUSE");  
  return 0;
}

我如何知道要使用哪种类型的内存?我什么时候吃的?

在以下情况下使用动态:

  1. 当你需要大量记忆的时候。典型的堆栈大小是1MB,所以任何大于50-100KB的东西都应该更好地动态分配,否则就有崩溃的风险。有些平台的限制甚至更低。

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

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

否则,首选堆栈分配。它速度更快,不会泄漏。

只有在运行时才知道分配的大小时,才使用动态内存。

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

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

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

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

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

这也可以确保您分配的内存与您真正需要的内存一样多。但是,由于是您在运行时分配的,因此必须使用free进行清理。

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

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

请注意,c99标准在C中引入了可变长度阵列(VLA),因此您不需要仅仅因为事先不知道阵列尺寸而使用动态内存分配(当然,除非是上面提到的#2

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

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

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 %xn", a, &a);
    printf("b = %d at address %xn", b, &b);
    printf("c = %d at address %xn", c[0], c);
    system("PAUSE");  
    return 0;
}

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

相关内容

  • 没有找到相关文章

最新更新