何时以及为何使用malloc?

pr1*_*m3x 51 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;
}
Run Code Online (Sandbox Code Playgroud)

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

tas*_*oor 48

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

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

这只是一个例子.在许多情况下需要动态分配.

看一下手册页malloc(3).

  • @Matt Joiner,这是一个例子。如果您认为这值得投反对票,那么我无话可说。 (5认同)
  • 仅仅因为未知在编译时需要多少内存,并不意味着必须涉及堆. (4认同)
  • 这个答案没有提到`malloc`非常重要的用途来分配内存,其生命周期超过当前块的执行时间. (2认同)

Nec*_*lis 25

您可以使用malloc,当你需要分配必须存在超出当前块(其中一个副本上的回报将是昂贵的为好)的执行生存期的对象,或者如果你需要分配内存大于该堆栈的大小(即:3mb本地堆栈数组是一个主意).

在C99引入VLA之前,您还需要它来执行动态大小的数组的分配,但是,它需要用于创建许多系统使用的树,列表和队列等动态数据结构.可能还有更多原因,这些只是少数几个.


Arc*_*nix 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
}
Run Code Online (Sandbox Code Playgroud)

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

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

  • 难道你不能只使用“&amp;p”传递一个指向函数的指针并仍然避免使用“malloc”吗? (3认同)

Dak*_*hah 8

让我们试着从不同的方面来解决这个问题

尺寸

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

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

范围

通常,声明的变量会在声明它的块之后被删除/释放(它们在堆栈上声明)。另一方面,使用分配内存的变量会malloc一直保留到手动释放它们的时间。

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

警告 - 返回与局部变量“匹配”关联的堆栈内存地址

有关更多详细信息,请阅读此

更改尺寸 ( realloc)

正如您可能已经猜到的那样,这是不可能的

错误检测

如果无法分配内存:正常方式可能会导致您的程序终止,而malloc将返回一个NULL可以在您的程序中轻松捕获和处理的

将来更改字符串内容

如果您创建存储字符串,就像char *some_memory = "Hello World";您不能做的some_memory[0] = 'h';那样,因为它存储为字符串常量,并且存储在其中的内存是只读的。如果您改用 malloc,您可以稍后更改内容。有关更多信息,请查看此答案

有关可变大小数组的更多详细信息,请查看此


Acn*_*Acn 6

malloc = 内存分配

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

Malloc 在 C 中执行完全相同的操作。它接受一个参数,即需要分配的内存大小,并返回一个指针变量,该变量指向您在内存中创建的整个内存块的第一个内存块。例子 -

int *p = malloc(sizeof(*p)*10);
Run Code Online (Sandbox Code Playgroud)

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

++您可以使用and运算符遍历每个块--

  • 你的意思是连续10个整数块? (4认同)