Cprogramming 简明教程
Memory Management in C
C 的一个重要特点是,编译器负责管理为代码中声明的变量分配内存的方式。一旦编译器分配了必需的字节内存,在运行时将无法对其进行更改。
编译器采用静态内存分配方法。但是,有时你可能需要在运行时按需分配内存。阅读本章,了解动态内存管理在 C 中的工作原理。
Functions for Dynamic Memory Management in C
C 编程语言提供了用于动态内存分配和管理的几个函数。这些函数可以在 <stdlib.h> header file 中找到。
Function |
Description |
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。 |
Allocating Memory Dynamically
如果你了解数组的大小,那么很容易,可以将其定义为数组。例如,如果你需要存储一个人的姓名,则可以安全地定义一个数组来容纳最多 100 个字符(假设一个姓名不包含超过 100 个字符)。所以,你可以如下定义一个数组:
char name[100];
这是 static memory allocation 的一个示例。现在我们考虑一种情况,你不知道需要存储的文本的长度,例如,你想存储关于某个主题的详细描述。在这种情况下,如果内容小于分配的大小,则该代码的执行期间会浪费掉已分配的内存。
另一方面,如果所需的大小超过已分配的内存大小,则可能导致不可预测的行为,包括导致数据损坏,因为数组的大小无法动态更改。
在这些情况下,你需要使用本章所述的动态内存分配方法。
The malloc() Function
此函数在 stdlib.h 头文件中定义。它分配所需大小的内存块,并返回一个 void pointer 。
void *malloc (size)
size 参数是指以字节为单位的内存块。要分配类型指定数据所需的内存,你需要使用 typecasting 运算符。
例如,以下代码片段分配存储 int 类型所需的内存:
int *ptr;
ptr = (int *) malloc (sizeof (int));
这里我们需要定义一个 pointer to character 而不用定义需要多少内存,稍后,基于需求,我们可以分配内存。
Example
以下示例使用 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\n");
} else {
printf("Name = %s\n", name);
}
}
编译并执行上述代码会产生以下输出:
Name = TutorialsPoint
The calloc() Function
calloc()函数(表示连续分配)分配请求的内存并返回其指针。
void *calloc(n, size);
此处,“n”是要分配的元素数量,“size”是每个元素的字节大小。
以下代码片段分配存储 10 个 int 类型所需内存:
int *ptr;
ptr = (int *) calloc(25, sizeof(int));
Example
我们用 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\n");
} else {
printf("Name = %s\n", name);
}
}
因此,你可完全控制并可在分配内存时传递任何大小的值,这与数组不同,后者一旦定义大小,你就无法更改它。
Resizing and Releasing the Memory
当程序退出时,操作系统会自动释放程序分配的所有内存。然而,在你不再需要使用已分配内存时通过调用 free() 函数明确释放已分配内存是一种很好的做法。
在本节中,我们将重点介绍 realloc() 和 free() 这两个函数的使用,你可使用它们来调整大小并释放已分配内存。
The realloc() Function
C 中的 realloc()(重新分配)函数用于动态更改先前分配的内存的内存分配。你可以通过调用 realloc() 函数来增加或减少已分配内存块的大小。
使用 realloc() 函数的原型如下所示:
void *realloc(*ptr, size);
其中,第一个参数“ ptr ”是先前已使用 malloc、calloc 或 realloc 分配要重新分配的内存块的指针。如果此指针为 NULL,将分配一个新块,且函数返回其指针。
第二个参数“ size ”是内存块的新大小(以字节为单位)。如果该值为“0”,且 ptr 指向现有的内存块,则 ptr 指向的内存块将被释放,且返回 NULL pointer 。
Example
以下示例演示在 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\n");
} else {
printf("Name = %s\n", name);
}
}
编译并执行上述代码会产生以下输出:
Name = TutorialsPoint India Private Limited
The free() Function
C 中的 free() 函数用于动态取消分配使用 malloc() 和 calloc() 等函数分配的内存,因为它们不会自行释放内存。
在 C 编程中,对未使用内存的任何引用都会创建垃圾存储,可能导致程序崩溃之类的问题。因此,明智的做法是使用 free() 函数对已分配内存执行手动清理操作。
以下是如何使用 free() 函数的原型:
void free(void *ptr);
其中 ptr 是先前已分配的内存块的指针。
Example
以下示例演示在 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\n");
} else {
printf("Name = %s\n", name);
free(name);
}
}
在代码结尾处,分配给 char * pointer 的内存被取消分配。
Name = TutorialsPoint India Private Limited