何时以及为何使用malloc?

时间:2012-01-10 08:40:08

标签: c malloc dynamic-memory-allocation

好吧,我无法理解何时以及为什么需要使用malloc来分配内存。

这是我的代码:

#include <stdlib.h>

int main(int argc, const char *argv[]) {

  typedef struct {
    char *name;
    char *sex;
    int age;
  } student;


  //Now I can do two things
  student p;

  //or
  student *ptr = (student *)malloc(sizeof(student));

  return 0;
}

为什么在我可以使用student p;时需要分配内存?

7 个答案:

答案 0 :(得分:42)

malloc用于动态内存分配。如上所述,它是动态分配,这意味着您在运行时分配内存。例如,当您在编译期间不知道内存量时。

一个例子应该清楚这一点。说你知道最多会有20名学生。因此,您可以创建一个包含静态20个元素的数组。您的阵列最多可容纳20名学生。但是,如果你不知道学生人数怎么办?说第一个输入是学生人数。它可能是10,20,50或其他任何东西。现在,您将在运行时输入n =学生数,并使用malloc动态分配大量内存。

这只是一个例子。有很多情况需要动态分配。

查看手册页malloc(3)

答案 1 :(得分:21)

当您需要分配在当前块的执行生命周期之外必须存在的对象时,使用malloc(其中返回的复制也很昂贵),或者如果您需要分配内存大于该堆栈的大小(即:3mb本地堆栈数组是的想法)。

在C99引入VLA之前,你还需要来执行动态大小的阵列的分配,但是,它需要用于创建动态数据结构,如树,列表和放大器。队列,被许多系统使用。可能还有很多原因,这些只是少数原因。

答案 2 :(得分:17)

稍微扩展一下这个例子的结构,考虑一下:

#include <stdio.h>

int main(int argc, const char *argv[]) {

typedef struct {
 char* name;
 char* sex;
 char* insurace;
 int age;
 int yearInSchool;
 float tuitionDue;
}student;


//Now I can do two things
student p;

//or
student *p = (student *)malloc(sizeof(student));

return 0
}

C a是通过值隐式传递的语言,而不是通过引用传递的语言。在这个例子中,如果我们将'p'传递给函数来对它做一些工作,我们将创建整个结构的副本。这使用额外的内存(特定结构需要多少空间),速度较慢,并且可能无法很好地扩展(在一分钟内更多)。但是,通过传递* p,我们不会传递整个结构。我们只在内存中传递一个引用此结构的地址。传递的数据量较小(指针大小),因此操作更快。

现在,了解这一点,想象一个程序(如学生信息系统),它必须创建和管理数千甚至数万的记录集。如果按值传递整个结构,则对一组数据进行操作所需的时间比将指针传递给每条记录要多。

答案 3 :(得分:4)

malloc =内存分配。

如果您使用过其他编程语言,则可能使用了“new”关键字。

Malloc在C中执行完全相同的操作。它需要一个参数,需要分配多大的内存,并返回一个指向

的第一个内存块的指针变量

您在内存中创建的整个内存块。示例 -

int *p = malloc(sizeof(int)*10);

现在,* p将指向内存上保留的连续20整数块的第一个块。

您可以使用++和 - 运算符遍历每个块。一切顺利。

答案 4 :(得分:0)

在这个例子中,它似乎确实无用。但现在想象你正在使用套接字或文件IO,并且必须读取可变长度的数据包,这些数据包只能在运行时阻止。或者在使用套接字时,每个客户端连接都需要服务器上的一些存储空间。你可以创建一个静态数组,但这会给你一个客户端限制,这将在编译时受到阻碍。

答案 5 :(得分:0)

让我们尝试从不同方面解决这个问题

大小

malloc允许您分配比仅使用student p;int x[n];分配的更大的内存空间。原因是malloc在堆上分配空间,而另一个在堆上分配空间

  

C编程语言静态,自动或动态地管理内存。静态持续时间变量通常与程序的可执行代码一起分配在主存储器中,并在程序的整个生命周期内保持不变。自动持续时间变量在堆栈上分配,随着函数的调用和返回而来去。对于静态持续时间和自动持续时间变量,分配的大小必须是编译时常量(可变长度自动数组[5]除外)。如果所需的大小直到运行时才知道(例如,如果要从用户或磁盘文件中读取任意大小的数据),则使用固定大小的数据对象是不够的。 (from Wikipedia

范围

通常,声明的变量将在声明该变量的块之后(在堆栈中声明)被删除/释放。另一方面,使用malloc分配了内存的变量将保留到手动释放它们为止。

这也意味着您无法在函数中创建变量/数组/结构并返回其地址(因为它指向的内存可能会被释放)。编译器还会通过发出警告来警告您:

  

警告-返回与本地变量'matches'相关的堆栈内存地址

有关更多详细信息,read this

更改大小(realloc

您可能已经猜到了,用通常的方式是不可能的

错误检测

如果无法分配内存:正常方式可能会导致程序终止,而malloc将返回NULL,可以很容易地在程序中捕获和处理

以后要更改字符串内容

如果创建存储类似char *some_memory = "Hello World";的字符串,则无法执行some_memory[0] = 'h';,因为它存储为字符串常量,并且存储在其中的内存是只读的。如果改用malloc,则以后可以更改内容。 有关更多信息,check this answer

有关可变大小数组的更多详细信息,请使用look at this

答案 6 :(得分:0)

当您需要分配必须存在于当前块的执行生命周期之外的对象时(其中复制返回也会很昂贵),或者如果您需要分配大于大小的内存,您可以使用 malloc那个堆栈