C 语言的内存管理
C 语言的一个重要特性是编译器负责管理代码中声明的变量的内存分配。一旦编译器分配了所需的内存字节,就无法在运行时更改。
编译器采用静态内存分配方法。但是,有时您可能需要在运行时按需分配内存。阅读本章以了解 C 语言中动态内存管理的工作原理。
C 语言中动态内存管理函数
C 编程语言提供了多个用于动态内存分配和管理的函数。这些函数可以在 <stdlib.h> 头文件 中找到。
函数 | 描述 |
---|---|
void *calloc(int num, int size); | 此函数分配一个由 num 个元素组成的数组,每个元素的大小为 size(以字节为单位)。 |
void free(void *address); | 此函数释放由地址指定的内存块。 |
void *malloc(size_t size); | 此函数分配一个包含 num 个字节的数组,并使其保持未初始化状态。 |
void *realloc(void *address, int newsize); | 此函数重新分配内存,并将其扩展到 newsize。 |
动态分配内存
如果您知道数组的大小,那么操作起来就很简单,您可以将其定义为数组。例如,如果您需要存储一个人的姓名,那么您可以安全地定义一个最多可容纳 100 个字符的数组(假设姓名不超过 100 个字符)。因此,您可以按如下方式定义数组:
char name[100];
这是一个静态内存分配的示例。现在让我们考虑一种您不知道需要存储的文本长度的情况,例如,您想要存储关于某个主题的详细描述。在这种情况下,如果内容小于分配的大小,则在程序执行期间分配的内存将被浪费。
另一方面,如果所需大小超过已分配的内存大小,则可能导致不可预测的行为,包括导致数据损坏,因为数组的大小无法动态更改。
在这种情况下,您需要使用本章所述的动态内存分配方法。
malloc() 函数
此函数定义在 stdlib.h 头文件中。它分配所需大小的内存块,并返回一个 void 指针。
void *malloc (size)
size 参数指的是内存块大小(以字节为单位)。要为指定数据类型分配所需的内存,您需要使用类型转换运算符。
例如,以下代码片段分配存储 int 类型所需的内存 -
int *ptr; ptr = (int *) malloc (sizeof (int));
这里我们需要定义一个指向字符的指针,但不定义所需的内存大小,之后根据需要分配内存。
示例
以下示例使用 malloc() 函数分配所需的内存来存储字符串(而不是声明固定大小的 char 数组)-
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { char *name; name = (char *) malloc(strlen("TutorialsPoint")); strcpy(name, "TutorialsPoint"); if(name == NULL) { fprintf(stderr, "Error - unable to allocate required memory "); } else { printf("Name = %s ", name); } }
输出
当编译并执行上述代码时,它会产生以下输出 -
Name = TutorialsPoint
calloc() 函数
calloc() 函数(代表连续分配)分配请求的内存并返回指向该内存的指针。
void *calloc(n, size);
其中,"n"表示要分配的元素数量,"size"表示每个元素的字节大小。
以下代码片段分配了存储 10 个 int 类型所需的内存 -
int *ptr; ptr = (int *) calloc(25, sizeof(int));
示例
让我们使用 calloc() 函数重写上面的程序。您需要做的就是将 malloc 替换为 calloc −
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { char *name; name = (char *) calloc(strlen("TutorialsPoint"), sizeof(char)); strcpy(name, "TutorialsPoint"); if(name == NULL) { fprintf(stderr, "Error - unable to allocate required memory "); } else { printf("Name = %s ", name); } }
因此,您可以完全控制内存分配,并且可以在分配内存时传递任意大小的值,这与数组不同,数组的大小一旦定义就无法更改。
调整大小和释放内存
程序运行时,操作系统会自动释放程序分配的所有内存。但是,当您不再需要使用分配的内存时,最好通过调用 free() 函数显式释放它。
在本节中,我们将重点介绍两个函数 realloc() 和 free() 的使用,您可以使用它们来调整分配的内存大小并释放它。
realloc() 函数
C 语言中的 realloc()(重新分配)函数用于动态更改先前分配的内存的分配。您可以通过调用 realloc() 函数来增加或减少已分配内存块的大小。
realloc() 函数的原型如下:
void *realloc(*ptr, size);
这里,第一个参数"ptr"是指向先前使用 malloc、calloc 或 realloc 分配的内存块的指针,该内存块将被重新分配。如果该参数为 NULL,则将分配一个新的内存块,并返回指向该内存块的指针。
第二个参数"size"是内存块的新大小,以字节为单位。如果值为"0",且 ptr 指向现有内存块,则 ptr 指向的内存块将被释放,并返回 NULL 指针。
示例
以下示例演示了如何在 C 程序中使用 realloc() 函数 -
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { char *name; name = (char *) calloc(strlen("TutorialsPoint"), sizeof(char)); strcpy(name, "TutorialsPoint"); name = (char *) realloc(name, strlen(" India Private Limited")); strcat(name, " India Private Limited"); if(name == NULL) { fprintf(stderr, "Error - unable to allocate required memory "); } else { printf("Name = %s ", name); } }
输出
上述代码编译并执行后,将产生以下输出:
Name = TutorialsPoint India Private Limited
free() 函数
C 语言中的 free() 函数用于动态释放使用 malloc() 和 calloc() 等函数分配的内存,因为这些内存不会被自动释放。
在 C 语言编程中,任何对未使用内存的引用都会产生垃圾回收,这可能导致程序崩溃等问题。因此,使用 free() 函数手动清理已分配的内存是明智之举。
以下是使用 free() 函数的原型:
void free(void *ptr);
其中 ptr 是指向先前分配的内存块的指针。
示例
以下示例演示了如何在 C 程序中使用 free() 函数 -
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { char *name; name = (char *) calloc(strlen("TutorialsPoint"), sizeof(char)); strcpy(name, "TutorialsPoint"); if(name == NULL) { fprintf(stderr, "Error - unable to allocate required memory "); } else { printf("Name = %s ", name); free(name); } }
输出
在代码的末尾,分配给 char * 指针 的内存被取消分配。
Name = TutorialsPoint India Private Limited