【C语言进阶(八)】动态内存管理

💓博主CSDN主页:杭电码农-NEO💓

⏩专栏分类:C语言学习分享⏪

🚚代码仓库:NEO的学习日记🚚

🌹关注我🫵带你学习更多C语言知识

🔝🔝



动态内存规划

  • [1. 前言](#1. 前言 "#1__14")
  • [2. 为什么要学动态内存管理?](#2. 为什么要学动态内存管理? "#2___40")
  • [3. 动态内存管理函数介绍](#3. 动态内存管理函数介绍 "#3__64")
  • [4. malloc函数详细介绍](#4. malloc函数详细介绍 "#4_malloc_81")
  • [5. free函数详细介绍](#5. free函数详细介绍 "#5_free_144")
  • [6. calloc函数详细介绍](#6. calloc函数详细介绍 "#6_calloc_191")
  • [7. realloc函数详细介绍](#7. realloc函数详细介绍 "#7_realloc_228")
  • [8. 总结以及拓展](#8. 总结以及拓展 "#8__285")

1. 前言

本章目标:

本篇文章
着重讲解动态内存
管理的四个函数

前期准备:

内存可以大致分为几个区域:

  • 栈区: 存放局部变量,函数
  • 堆区: 存放动态开辟的空间
  • 静态区 : 全局变量,static修饰变量
  • 代码区: 常量字符串

今天的主角就是在堆区申请空间的:
动态内存管理!


2. 为什么要学动态内存管理?

我们平常使用数组时:

c 复制代码
int arr[6]={1,2,3,4,5,6};

这是在栈区开辟的空间
并且它的大小是固定的,被初始化成6

原因一:

很多情况下,我们需要的空间大小
在程序运行后才知道,此时数组不管用了
只能尝试使用动态内存管理的方式了
!

原因二:

在做题时经常遇见需要手动动态
开辟空间的题目,且在笔试中也经常考察


3. 动态内存管理函数介绍

动态内存管理有四个函数:

1. malloc
2. calloc
3. realloc
4. free

这些函数定义在头文件: stdlib.h中

前两个是用于开辟空间的
realloc是用于扩容的
而free是释放空间的


4. malloc函数详细介绍

先看它在cplusplus上的定义:

我直接把要点翻译过来:

  • 功能:它向内存申请一块连续可用的空间
  • 申请空间成功就返回指向这块空间的指针
  • 申请空间失败就返回空指针NULL
  • 返回类型是void *
    它可以申请任一类型的空间
  • 参数size的单位是字节
    开辟size个字节的空间

需要注意的地方:

  1. 它的返回类型是void*,你在开辟空间时
    应强制类型转换成你要开辟的空间的类型
c 复制代码
struct S
{
  int a;
  char cc;
  double d;
};

int* p = (int*)malloc(40);
char* arr = (char*)malloc(10);
struct S* ss = (struct S*)malloc(20);

总结:开辟什么类型的空间就强转成什么


  1. malloc有可能申请空间失败
    所以每次开辟空间后要判断指针是否为空
    若指针为空应该直接终止掉程序
c 复制代码
int* p = (int*)malloc(40);
if(p == NULL)
{
	printf("动态申请失败");
	exit(-1)//退出程序
}
else //不为空再去使用它
{
	//......
}

总结:每次开辟空间后要判断空指针


5. free函数详细介绍

先看free在官网上的定义:

将要点翻译过来:

  • free用于释放动态开辟的空间
  • 参数ptr指向的空间必须是动态开辟的
  • 若ptr是空指针,则free函数什么都不做

需要注意的地方:

  1. free释放的空间必须在堆区
    也就是必须是动态开辟的内存
c 复制代码
//堆区开辟的空间
int* p = (int*)malloc(40);
//栈区开辟的空间
int arr[4] = {1,2,3,4};
//正确的用法
free(p);
//错误的用法
free(arr);

总结:free释放的空间必须在堆区


  1. 被free释放后的空间就还给操作系统了
    但是指针还是指向已经释放的空间
    所以在free释放掉一块空间后
    还要将指针赋值为空才安全
c 复制代码
int* p = (int*)malloc(40);
free(p);
p = NULL;

总结:释放掉空间后记得要置空


6. calloc函数详细介绍

先看calloc的定义:

重点翻译:

  • 参数num是要开辟的空间个数
  • 参数size是每份空间所占字节数
  • calloc不仅会开辟空间
    还将所有数据初始化为0
  • 它和malloc的区别就是前者会初始化

使用举例:

c 复制代码
//开辟10个整型空间
int* p = (int*)calloc(10,sizeof(int));
if(p == NULL)
{
	printf("开辟失败");
	exit(-1);
}
else
{
	//......
}

可以在不同场景选择使用
malloc或者calloc


7. realloc函数详细介绍

先看realloc的定义:

重点翻译:

  • 参数ptr是指向要扩容的空间的指针
  • 参数size是扩容后空间总大小
    单位是字节
  • 返回值为扩容之后的内存起始位置
  • 此函数在调整原先空间大小的基础上
    还会将原先空间的内容拷贝过来

需要注意的地方:

  1. realloc扩容的空间必须在堆区
c 复制代码
int* p = (int*)malloc(40);
int arr[4]={1,2,3,4};
//正确用法
int* pp = (int*)realloc(p,60);
//错误用法
int* parr = (int*)realloc(arr,30);

  1. 若参数ptr是空指针NULL
    则realloc的功能相当于malloc
c 复制代码
int* p = NULL;
int* pp = (int*)realloc(p,40);

此时的realloc相当于malloc


  1. realloc扩容后,原先指向
    这块空间的指针会自动置空
    不需要再手动置空
c 复制代码
int* p = (int*)malloc(40);
int* pp = (int*)realloc(p,60);

free(pp);
pp=NULL;

总结:realloc扩容后,原先的指针可以不管


8. 总结以及拓展

动态开辟的内存在堆区上
而我们定义的指针却在栈区上
所以可以这样理解这个过程:


🔎 下期预告:常见动态内存错误 🔍

相关推荐
2035去旅行2 小时前
bootcmd 详细讲解
linux·嵌入式·arm·soc
陈希1233 小时前
Linux 防火墙配置实战:firewalld、iptables 与云安全组
linux·运维·服务器
女神下凡4 小时前
芯参谋(95):嵌入式文件系统_开发指南
linux·服务器·arm开发·驱动开发·设计规范
且从容.7 小时前
Ubuntu安装flume
linux·ubuntu·flume
承渊政道7 小时前
Linux网络学习【Reactor反应堆模式】
linux·网络·学习·ubuntu·reactor
且从容.10 小时前
ubuntu安装flink
linux·ubuntu·flink
爱和冰阔落12 小时前
【Linux网络】TCP 服务器如何并发处理多个客户端?从 fork、僵尸进程到双重 fork
linux·运维·服务器·网络
程序员沉梦听雨12 小时前
WSL2的安装与使用
linux·wsl
微小的鱼12 小时前
Linux的渲染与显示系统链路
android·java·linux
lisanmengmeng13 小时前
alertmanger 标签 rules 打上分组标签
linux·运维·服务器