大家好,我是网域小星球。
之前我们用数组时,大小必须提前写死,比如 int arr[50]。但实际开发中,我们常常不知道要存多少数据 ,这时候就需要动态内存。
动态内存可以在程序运行时随时申请、随时释放,非常灵活,是进阶必备知识点。
目录
[2. free ------ 释放内存](#2. free —— 释放内存)
[4. realloc ------ 扩容 / 缩容](#4. realloc —— 扩容 / 缩容)
一、本章学习目标
- 理解栈内存与堆内存的区别
- 掌握
malloc动态申请内存 - 掌握
free释放内存,避免内存泄漏 - 理解
calloc与malloc的区别 - 掌握
realloc调整内存大小 - 野指针、空指针、内存泄漏等常见问题
二、为什么要用动态内存?
- 数组大小固定,不够灵活
- 数据少时浪费空间,数据多时溢出
- 动态内存:用多少申请多少,不用就释放
三、四个核心函数
头文件:
cpp
#include <stdlib.h>
- malloc ------ 申请内存
cpp
void *malloc(size_t size);
示例:申请 4 个 int
cpp
int *p = (int *)malloc(4 * sizeof(int));
- 成功:返回指向内存的指针
- 失败:返回
NULL,必须判断!
2. free ------ 释放内存
cpp
free(p);
p = NULL; // 非常重要,避免野指针
- calloc ------ 申请并初始化为 0
cpp
int *p = (int *)calloc(4, sizeof(int));
每个字节都置 0。
4. realloc ------ 扩容 / 缩容
cpp
p = (int *)realloc(p, 8 * sizeof(int));
四、完整示例:动态数组
cpp
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n;
printf("请输入数组长度:");
scanf("%d", &n);
// 动态申请
int *p = (int *)malloc(n * sizeof(int));
if (p == NULL)
{
printf("申请失败\n");
return 1;
}
// 赋值
for (int i = 0; i < n; i++)
{
p[i] = i + 1;
}
// 打印
for (int i = 0; i < n; i++)
{
printf("%d ", p[i]);
}
// 释放
free(p);
p = NULL;
return 0;
}
五、动态内存实现可扩容学生管理
结合上一章项目,我们可以实现不限人数的学生管理。
cpp
struct Student *stus;
int count = 0;
int capacity = 0;
// 初始化
stus = (struct Student *)malloc(10 * sizeof(struct Student));
capacity = 10;
// 满了就扩容
if (count >= capacity)
{
stus = (struct Student *)realloc(stus, (capacity + 10) * sizeof(struct Student));
capacity += 10;
}
六、高频易错点
- 不判断
malloc返回NULL直接使用 - 只
malloc不free,造成内存泄漏 free后继续使用,变成野指针- 重复
free同一块内存 - 越界读写动态数组
七、本章总结
- 动态内存从堆上申请,灵活可控
malloc申请,free释放,必须成对出现calloc会自动清零realloc用于扩容- 释放后置空指针,避免野指针
- 是实现高性能、灵活项目的必备基础
下期预告
C 语言从 0 入门(十七)|结构体指针 + 动态内存综合实战下一篇我们把结构体、指针、动态内存、文件操作全部融合,打造一个真正可商用的小型管理系统。