跳到主要内容

C 语言动态内存分配

介绍

在C语言中,内存管理是一个非常重要的概念。程序运行时,内存通常分为两部分。栈用于存储局部变量和函数调用信息,而堆则用于动态内存分配。动态内存分配允许程序在运行时根据需要申请和释放内存,这在处理不确定大小的数据时非常有用。

C语言提供了几个标准库函数来实现动态内存分配,包括 malloccallocreallocfree。本文将详细介绍这些函数的使用方法,并通过实际案例帮助你理解它们的应用场景。

动态内存分配的基本函数

1. malloc 函数

malloc 是C语言中最常用的动态内存分配函数。它的原型如下:

c
void* malloc(size_t size);
  • size:需要分配的内存大小(以字节为单位)。
  • 返回值:成功时返回指向分配内存的指针,失败时返回 NULL

示例

c
#include <stdio.h>
#include <stdlib.h>

int main() {
int *ptr;
int n = 5;

// 分配内存以存储5个整数
ptr = (int*) malloc(n * sizeof(int));

if (ptr == NULL) {
printf("内存分配失败\n");
return 1;
}

// 初始化分配的内存
for (int i = 0; i < n; i++) {
ptr[i] = i + 1;
}

// 打印分配的内存内容
for (int i = 0; i < n; i++) {
printf("%d ", ptr[i]);
}

// 释放内存
free(ptr);

return 0;
}

输出:

1 2 3 4 5
备注

malloc 分配的内存是未初始化的,可能包含随机值。如果需要初始化内存,可以使用 calloc

2. calloc 函数

calloc 函数用于分配内存并将其初始化为零。它的原型如下:

c
void* calloc(size_t num, size_t size);
  • num:需要分配的元素数量。
  • size:每个元素的大小(以字节为单位)。
  • 返回值:成功时返回指向分配内存的指针,失败时返回 NULL

示例

c
#include <stdio.h>
#include <stdlib.h>

int main() {
int *ptr;
int n = 5;

// 分配内存以存储5个整数,并初始化为0
ptr = (int*) calloc(n, sizeof(int));

if (ptr == NULL) {
printf("内存分配失败\n");
return 1;
}

// 打印分配的内存内容
for (int i = 0; i < n; i++) {
printf("%d ", ptr[i]);
}

// 释放内存
free(ptr);

return 0;
}

输出:

0 0 0 0 0
提示

calloc 适合需要初始化内存的场景,例如数组或结构体的初始化。

3. realloc 函数

realloc 函数用于调整已分配内存的大小。它的原型如下:

c
void* realloc(void* ptr, size_t size);
  • ptr:指向之前分配的内存块的指针。
  • size:新的内存大小(以字节为单位)。
  • 返回值:成功时返回指向新内存块的指针,失败时返回 NULL

示例

c
#include <stdio.h>
#include <stdlib.h>

int main() {
int *ptr;
int n = 5;

// 分配内存以存储5个整数
ptr = (int*) malloc(n * sizeof(int));

if (ptr == NULL) {
printf("内存分配失败\n");
return 1;
}

// 初始化分配的内存
for (int i = 0; i < n; i++) {
ptr[i] = i + 1;
}

// 调整内存大小以存储10个整数
ptr = (int*) realloc(ptr, 10 * sizeof(int));

if (ptr == NULL) {
printf("内存重新分配失败\n");
return 1;
}

// 初始化新增的内存
for (int i = n; i < 10; i++) {
ptr[i] = i + 1;
}

// 打印分配的内存内容
for (int i = 0; i < 10; i++) {
printf("%d ", ptr[i]);
}

// 释放内存
free(ptr);

return 0;
}

输出:

1 2 3 4 5 6 7 8 9 10
警告

realloc 可能会移动内存块到新的位置,因此需要更新指针。

4. free 函数

free 函数用于释放之前分配的内存。它的原型如下:

c
void free(void* ptr);
  • ptr:指向需要释放的内存块的指针。
注意

释放内存后,指针应设置为 NULL,以避免悬空指针问题。

实际应用场景

动态数组

动态内存分配最常见的应用之一是创建动态数组。例如,当数组大小在编译时未知时,可以使用 malloccalloc 来分配内存。

c
#include <stdio.h>
#include <stdlib.h>

int main() {
int *arr;
int n;

printf("请输入数组大小: ");
scanf("%d", &n);

// 分配内存以存储n个整数
arr = (int*) malloc(n * sizeof(int));

if (arr == NULL) {
printf("内存分配失败\n");
return 1;
}

// 初始化数组
for (int i = 0; i < n; i++) {
arr[i] = i * 2;
}

// 打印数组内容
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}

// 释放内存
free(arr);

return 0;
}

动态字符串

另一个常见应用是动态字符串处理。例如,读取用户输入并动态分配内存来存储字符串。

c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
char *str;
int len;

printf("请输入字符串长度: ");
scanf("%d", &len);

// 分配内存以存储字符串
str = (char*) malloc((len + 1) * sizeof(char));

if (str == NULL) {
printf("内存分配失败\n");
return 1;
}

// 读取字符串
printf("请输入字符串: ");
scanf("%s", str);

// 打印字符串
printf("输入的字符串是: %s\n", str);

// 释放内存
free(str);

return 0;
}

总结

动态内存分配是C语言中非常重要的功能,它允许程序在运行时灵活地管理内存。通过 malloccallocreallocfree 函数,你可以根据需要分配和释放内存,从而处理不确定大小的数据。

提示

始终检查内存分配函数的返回值,以确保内存分配成功。

附加资源

通过本文的学习,你应该已经掌握了C语言动态内存分配的基本概念和使用方法。接下来,尝试编写一些程序来巩固你的知识吧!