C 内存管理示例
实际内存管理示例
为了演示动态内存的实际应用,我们编写了一个可以生成任意长度列表的程序。
C 语言中的普通数组长度固定且无法更改,但使用动态内存,我们可以创建任意长度的列表:
示例
struct list {
int *data; // 指向存储列表项的内存位置。
int numItems; // 指示列表中当前有多少个项目
int size; // 表示分配的内存可以容纳多少个项目
};
void addToList(struct list *myList, int item);
int main() {
struct list myList;
int amount;
int i, j;
// 创建一个清单,并预留足够的空间容纳 10 项内容。
myList.numItems = 0;
myList.size = 10;
myList.data = malloc(myList.size * sizeof(int));
// 确定内存分配是否成功
if (myList.data == NULL) {
printf("Memory allocation failed");
return 1; // 程序退出并返回错误代码
}
// 向列表中添加任意数量的项目,数量由 amount 变量指定。
amount = 44;
for (i = 0; i < amount; i++) {
addToList(&myList, i + 1);
}
// 显示列表内容
for (j = 0; j < myList.numItems; j++) {
printf("%d ", myList.data[j]);
}
// 不再需要内存时,请释放它。
free(myList.data);
myList.data = NULL;
return 0;
}
// 此函数向列表中添加项目
void addToList(struct list *myList, int item) {
// 如果列表已满,则调整内存大小以容纳另外 10 个项目。
if (myList->numItems == myList->size) {
int newSize = myList->size + 10;
// 使用临时指针,这样即使失败也不会丢失原始指针。
int *tmp = realloc(myList->data, newSize * sizeof(int));
if (tmp == NULL) {
printf("Memory resize failed
");
return; // 列表保持不变。
}
// 仅在成功重新分配后更新字段
myList->data = tmp;
myList->size = newSize;
}
// 将该项添加到列表末尾
myList->data[myList->numItems] = item;
myList->numItems++;
}
亲自试一试 »
指向结构的指针: 此示例包含一个指向结构体 `myList` 的指针。由于我们使用的是指向结构的指针而不是结构体本身,因此我们使用箭头语法(`->`)来访问结构体的成员。
示例详解
本示例包含三个部分:
- 包含列表数据的结构体
myList - 包含程序的
main()函数。 - 向列表添加元素的
addToList()函数。
myList 结构
myList 结构包含列表的所有信息,包括其内容。它有三个成员:
data- 指向包含列表内容的动态内存的指针numItems- 指示列表中的项数size- 表示分配的内存可以容纳多少个项目
我们使用结构体,以便轻松地将所有这些信息传递给函数。
main() 函数
main() 函数首先初始化一个可容纳 10 个元素的列表:
// 创建一个清单,并预留足够的空间容纳 10 项内容。
myList.numItems = 0;
myList.size = 10;
myList.data = malloc(myList.size * sizeof(int));
myList.numItems 设置为 0,因为列表初始为空。
myList.size 用于跟踪已分配的内存大小。我们将其设置为 10,因为我们将为 10 个元素分配足够的内存。
然后我们分配内存,并将指向该内存的指针存储在 myList.data 中。
接下来我们添加错误检查,以确定内存分配是否成功。
// 确定内存分配是否成功
if (myList.data == NULL) {
printf("Memory allocation failed");
return 1; // 程序退出并返回错误代码
}
如果一切正常,循环会使用 addToList() 函数向列表中添加 44 个项目:
// 向列表中添加任意数量的项目,数量由 amount 变量指定。
amount = 44;
for (i = 0; i < amount; i++) {
addToList(&myList, i + 1);
}
在上面的代码中,&myList 是指向列表的指针,i + 1 是我们想要添加到列表中的数字。我们选择 i + 1 是为了让列表从 1 而不是 0 开始。您可以选择任何数字添加到列表中。
所有项目添加到列表后,下一个循环会打印列表的内容。
// 显示列表内容
for (j = 0; j < myList.numItems;
j++) {
printf("%d ", myList.data[j]);
}
打印完列表后,我们会释放内存以防止内存泄漏。
// 不再需要内存时,请释放内存。
free(myList.data);
myList.data = NULL;
addToList() 函数
addToList() 函数用于向列表中添加项目。它接受两个参数:
void addToList(struct list *myList, int item)
- 指向列表的指针。
- 要添加到列表中的值。
该函数首先检查列表是否已满,方法是将列表中的元素数量与列表的大小(容量)进行比较。
如果列表已满,它会尝试扩展内存以容纳另外 10 个元素。
我们使用一个临时指针和realloc,这样即使调整大小失败,我们也不会丢失原始内存块。
data和size。
// 如果列表已满,则调整内存大小以容纳另外 10 个项目。
if (myList->numItems == myList->size) {
int newSize = myList->size + 10;
// 使用临时指针,这样即使失败也不会丢失原始指针。
int *tmp = realloc(myList->data, newSize * sizeof(int));
if (tmp == NULL) {
printf("Memory resize failed
");
return; // 列表保持不变。
}
// 仅在成功重新分配后更新字段
myList->data = tmp;
myList->size = newSize;
}
最后,该函数将项目添加到列表末尾。索引 myList->numItems 始终位于列表末尾,因为每次添加新项目时,该索引都会递增 1。
// 将该项添加到列表末尾
myList->data[myList->numItems] = item;
myList->numItems++;
为什么我们每次只预留 10 个项目?
优化需要在内存和性能之间取得平衡。即使我们分配了一些未使用的内存,频繁地重新分配内存也会降低效率。内存分配过多和分配过于频繁之间存在一个平衡点。
在这个例子中,我们选择了 10 这个数字,但这取决于您预期的数据量以及数据变化的频率。例如,如果我们事先知道会有 44 个项目,那么我们可以一次性分配 44 个项目的内存。
完整的标准库参考
如需完整的内存管理函数和标准库中其他函数的参考,请访问C<stdlib.h>库参考。

