C语言 — 动态内存管理(动态内存函数)

前言

本期分为三篇介绍动态内存管理相关内容,关注博主了解更多
博主博客链接:https://blog.csdn.net/m0_74014525
本期介绍动态内存函数,函数如何使用、函数格式、在使用在所需要的注意点及C/C++程序的内存开辟区域


系列文章

第一篇:C语言 — 动态内存管理(动态内存函数)
第二篇:C语言 — 常见的动态内存错误
第三篇:C语言 — 柔性数组


文章目录

  • 前言
  • 系列文章
  • 一、动态内存分配是什么
  • 二、为什么存在动态内存分配
  • 三、动态内存函数的介绍
    • 1. malloc
    • 2. free
    • 3. calloc
    • 4. realloc
  • 四、C/C++程序的内存开辟
    • 1. 内存分配区域
  • 总结

一、动态内存分配是什么

动态内存分配是指在程序运行期间由程序自己向操作系统请求分配一定大小的内存空间,以存储程序运行时所需的数据。 由于动态分配的内存空间在程序运行期间是可变的,所以它比静态分配更加灵活。

动态内存分配带来的好处是可以根据实际需要动态调整内存大小,从而避免浪费内存。 但是,如果程序员不小心管理动态分配的内存,就可能会导致内存泄漏或者内存溢出等问题,严重影响程序的性能和稳定性。因此,使用动态内存分配时需要注意内存的释放和管理。

常见的动态内存分配函数有 malloccallocrealloc 等。其中 malloc 分配指定大小的内存块,calloc 分配并初始化一定数量的内存块,realloc 可以重新调整已分配的内存块的大小。

二、为什么存在动态内存分配

我们已经掌握的内存开辟方式有:

int val = 20;//在栈空间上开辟四个字节
char arr[10] = {0};//在栈空间上开辟10个字节的连续空间

但是上述的开辟空间的方式有两个特点:

  1. 空间开辟大小是固定的。
  2. 数组在申明的时候,必须指定数组的长度,它所需要的内存在编译时分配。

但是对于空间的需求,不仅仅是上述的情况。
有时候我们需要的空间大小在程序运行的时候才能知道,
那数组的编译时开辟空间的方式就不能满足了。
这时候就只能试试动态存开辟了。

三、动态内存函数的介绍


1. malloc

malloc函数在C语言中用于在程序运行时向内存申请一块指定大小的内存空间。

函数格式:

void* malloc (size_t size);

其中,size_t是一个无符号整数类型,用于表示申请内存的字节数。malloc函数返回一个void指针,指向分配的内存空间的起始地址。如果分配失败,malloc函数返回空指针NULL。

函数特点:

  • 如果开辟成功,则返回一个指向开辟好空间的指针。
  • 如果开辟失败,则返回一个NULL指针,因此malloc的返回值一定要做检查。
  • 返回值的类型是 void* ,所以malloc函数并不知道开辟空间的类型,具体在使用的时候使用者自己来决定。
  • 如果参数 size 为0,malloc的行为是标准是未定义的,取决于编译器。

使用malloc函数申请内存时,需要注意以下几点:

1.申请的内存大小应该是变量或数据类型的字节数乘以需要存储或操作的元素个数,以保证申请到足够的内存空间。
2.申请到的内存空间必须使用free函数进行释放,否则会导致内存泄露。
3.申请到的内存空间不会被自动初始化,即其中的数据是随机的,需要手动进行初始化。

举例演示:

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

int main() {
    int *p;
    p = (int*)malloc(10*sizeof(int)); //申请10个int类型数据的内存空间
    if (p == NULL) { //判断申请是否成功
        printf("Memory allocation failed.");
        exit(1);
    }
    for (int i = 0; i < 10; i++) { //手动初始化数据
        *(p+i) = i;
    }
    for (int i = 0; i < 10; i++) { //输出数据
        printf("%d\t", *(p+i));
    }
    free(p); //释放内存空间
    p=NULL;  //将指针置为空
    return 0;
}
 

2. free

free 函数是 C 语言中用来释放动态分配的内存的函数

函数格式:

void free (void* ptr);

其中,ptr 是之前调用 malloc、calloc 或 realloc函数返回的指针。调用 free 函数后,指针所指向的内存将会被操作系统回收,可以再次被分配给其他程序使用。
函数特点:

  • 如果参数 ptr 指向的空间不是动态开辟的,那free函数的行为是未定义的。
  • 如果参数 ptr 是NULL指针,则函数什么事都不做。

使用 free 函数的时候需要注意以下几点:

1.只能释放动态分配的内存,不能释放栈或全局变量中的内存。
2.如果多次释放同一个指针,会导致程序异常。
3.如果指针为空指针(NULL),则不会进行任何操作。

3. calloc

calloc函数是C语言中的一个内存分配函数,用于在内存中分配指定大小的连续空间,并将其中的每个字节都初始化为0。
函数格式:

void* calloc (size_t num, size_t size);

其中,num表示要分配的元素数量,size表示每个元素的大小。函数返回一个指向新分配内存的指针,如果分配失败则返回NULL。
函数特点:

  • 与函数 malloc 的区别只在于 calloc 会在返回地址之前把申请的空间的每个字节初始化为全0。
  • 与malloc函数不同,calloc函数在分配内存时会自动清空分配的内存空间,所以一般用于需要初始化内存的情况。但它的缺点是比malloc函数慢,因为它需要在分配内存时进行清空操作。

使用calloc函数申请内存时,需要注意以下几点:

1.申请的内存大小应该是变量或数据类型的字节数乘以需要存储或操作的元素个数,以保证申请到足够的内存空间。
2.申请到的内存空间必须使用free函数进行释放,否则会导致内存泄露。
3.申请到的内存空间不会被自动初始化,即其中的数据是随机的,需要手动进行初始化。
4.区别于malloc,calloc 会在返回地址之前把申请的空间的每个字节初始化为全0。

举例演示:

#include <stdio.h>
#include <stdlib.h>
int main()
{
	int* p = (int*)calloc(10, sizeof(int));
	if (NULL != p)
	{
		//使用空间
	}
	free(p);
	p = NULL;
	return 0;
}

在这里插入图片描述
如何对申请的内存空间的内容要求初始化,那么可以很方便的使用calloc函数来完成任务


4. realloc

realloc函数是C语言中的一个库函数,用于重新分配动态分配的内存空间。
1.用于调整现有的内存块大小、
2.分配新的内存块
3.用于释放现有的内存块,当传递给它一个空指针时。

函数格式:

void* realloc(void* ptr, size_t size);

ptr表示指向已经动态分配的内存块的指针。
size表示需要重新分配的内存块的新尺寸。
返回值:如果分配失败,则返回NULL指针;否则返回一个新的指针,指向重新分配后的内存块。

函数特点:

使用realloc函数申请内存时,需要注意以下几点:

1.如果新的尺寸大于旧的尺寸,realloc函数将在原来的内存块后面分配额外的内存,使其达到新的尺寸。
2.如果新的尺寸小于旧的尺寸,realloc函数将会释放一部分内存,使其达到新的尺寸。
3.如果ptr是空指针,则等同于调用malloc函数。如果size是0,等同于调用free函数。

realloc在调整内存空间的是存在两种情况:

  • 情况1:原有空间之后有足够大的空间
  • 情况2:原有空间之后没有足够大的空间
    在这里插入图片描述

情况1:
当是情况1 的时候,要扩展内存就直接原有内存之后直接追加空间,原来空间的数据不发生变化。

情况2:
当是情况2 的时候,原有空间之后没有足够多的空间时,
扩展的方法是:在堆空间上另找一个合适大小的连续空间来使用。这样函数返回的是一个新的内存地址。
由于上述的两种情况,realloc函数的使用就要注意一些。

四、C/C++程序的内存开辟

在这里插入图片描述

1. 内存分配区域

C/C++程序内存分配的几个区域:

栈区(stack)在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。 栈区主要存放运行函数而分配的局部变量、函数参数、返回数据、返回地址等。
堆区(heap)一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。分配方式类似于链表。
数据段 (静态区)(static)存放全局变量、静态数据。程序结束后由系统释放。
代码段存放函数体(类成员函数和全局函数)的二进制代码。

总结

本期博客的重要点概况:
malloc函数:用于动态内存的开辟
calloc函数:也是用于动态内存开辟,区别于malloc,calloc函数会将每一个字节初始化为0
realloc函数:用于扩展内存空间,需要注意增加内存的返回,分为情况1和2
free函数:用于释放动态内存空间


如这篇博客对大家有帮助的话,希望 三连 支持一下 !!! 如果有错误感谢大佬的斧正 如有 其他见解发到评论区,一起学习 一起进步。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/62446.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

RGB_LCD简介

文章目录 前言一、LCD原理1、构造2、分辨率3、像素格式4、LCD接口5、ATK-7016 的屏幕接口原理图 二、LCD时序1、时间参数2、行场时序1、行显示时序&#xff1a;2、场显示时序&#xff1a;3、数据同步模式4、像素时钟 三、总结四、参考资料 前言 LCD (Liquid Crystal Display)是…

数据结构——双链表

我宁愿靠自己的力量&#xff0c;打开我的前途&#xff0c;而不愿求有力者垂青 文章目录 双线向链表各接口函数名或变量名 双向链表接口实现源码 快速索引【头文件及函数声明】 双向链表接口实现 双向链表的构造分析 双向链表的定义及初始化 双向链表的插入和删除 往期…

音频客观感知MOS对比,对ViSQOL、PESQ、MosNet(神经网络MOS分)和polqa一致性对比和可信度验证

原创&#xff1a;转载需附链接&#xff1a; https://blog.csdn.net/qq_37100442/article/details/132057139?spm1001.2014.3001.5502 一、背景 Mos分评价音质重要指标&#xff0c;最近也有很多机构和公司在研究适合自己的评价体系。目前Mos分主要分为主观评测和客观感知评价。…

智能仪表板DevExpress Dashboard v23.1亮点 - 增强对自定义导出的支持

DevExpress Dashboard v23.1版本增强了自定义导出到Excel的功能等&#xff0c;欢迎下载最新版本体验&#xff01; DevExpress Dashboard v23.1正式版下载(Q技术交流&#xff1a;523159565&#xff09; 所有平台 导出自定义仪表板项目到Excel 用户现在可以在WinForms和Web应…

危大工程智慧工地源码,微服务+Java+Spring Cloud +UniApp +MySql 物联网、人工智能、视频AI分析

一套智慧工地管理平台源码&#xff0c;PC端移动APP端可视货数据管理端源码 智慧工地可视化系统利用物联网、人工智能、云计算、大数据、移动互联网等新一代信息技术&#xff0c;通过工地中台、三维建模服务、视频AI分析服务等技术支撑&#xff0c;实现智慧工地高精度动态仿真&a…

C++ 多线程:std::future

std::future std::future 简介示例1博客引用来源 std::future 简介 我们前面介绍的std::thread 是C11中提供异步创建多线程的工具&#xff0c;只能是异步运行任务&#xff0c;却无法获取任务执行的结果&#xff0c;一般都是依靠全局对象&#xff0c;全局对象在多线程下是及其不…

4 三组例子,用OpenCV玩转图像-AI-python

读取&#xff0c;缩放&#xff0c;旋转&#xff0c;写入图像 首先导入包&#xff0c;为了显示导入matplotlib/为了在matplotlib显示 导入CV2/查看版本 导入图片/查看图片类型 图片数组 数组大小 对于opencv通道顺序蓝色B、绿色G、红色R matplotlib通道顺序为 红色R、绿色G、蓝…

快速修复应用程序中的问题的利器—— Android热修复

热修复技术在Android开发中扮演着重要的角色&#xff0c;它可以帮助开发者在不需要重新发布应用程序的情况下修复已经上线的应用程序中的bug或者添加新的功能。 一、热修复是什么&#xff1f; 热修复&#xff08;HotFix&#xff09;是一种在运行时修复应用程序中的问题的技术…

彻底弄清楚Minor GC和Major GC及Full GC

系列资源汇总 https://gitee.com/xiayi/java-docs 每日一句 每一日你所付出的代价都比前一日高&#xff0c;因为你的生命又消短了一天&#xff0c;所以每一日你都要更用心。 前提概要 对于JVM而言&#xff0c;最难能够掌握的就是GC回收部分的研究和探索。 而对于虚拟机而言根据…

前端页面--视觉差效果

代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><link rel"stylesheet" href"https://un…

如何实现基于场景的接口自动化测试用例?

自动化本身是为了提高工作效率&#xff0c;不论选择何种框架&#xff0c;何种开发语言&#xff0c;我们最终想实现的效果&#xff0c;就是让大家用最少的代码&#xff0c;最小的投入&#xff0c;完成自动化测试的工作。 基于这个想法&#xff0c;我们的接口自动化测试思路如下…

【Linux】【预】配置网络IP,挂载网络目录

【Linux】【预】配置网络IP&#xff0c;挂载网络目录 1. 配置查看IP2.配置Linux中的IP3. 串口连接开发板&#xff0c;配置 1. 配置查看IP a . 查看ipifconfig如下操作&#xff0c;其中的&#xff1a;192.168.252.140就是它的IP b . 使用xmodem 连接到虚拟机&#xff0c;最后点…

Docker搭建zookeeper

问题背景 前言 本文参考自&#xff1a;docker-compose快速搭建Zookeeper集群还有一种更加详细更加全面的部署方式&#xff1a;Docker之docker-compose一键部署Zookeeper集群&#xff0c;但笔者还未验证&#xff0c;先记录下来 搭建 安装docker-ce 此处不赘述 安装docker-co…

Docker快速入门笔记

Docker快速入门 前言 当今软件开发领域的一股热潮正在迅速兴起&#xff0c;它融合了便捷性、灵活性和可移植性&#xff0c;让开发者们欣喜若狂。它就是 Docker&#xff01;无论你是一个初学者&#xff0c;还是一位经验丰富的开发者&#xff0c;都不能错过这个引领技术浪潮的工…

MYSQL进阶-事务的基础知识

1.什么是数据库事务&#xff1f; 就是把好几个sql语句打包成一个整体执行&#xff0c;要么全部成功&#xff0c;要么全部失败&#xff01;&#xff01;&#xff01; 事务是一个不可分割的数据库操作序列&#xff0c;也是数据库并发控制的基本单位&#xff0c;其执 行的结果必…

03_012slab块分配器,管理内核内存分配,管理高速缓存

物理背景 为什么会有缓存cache 在最初开发ARM架构时&#xff0c;处理器的时钟速度和内存的访问速度大致相同。今天的处理器内核要复杂得多&#xff0c;其时钟速度可以快上几个数量级。但是&#xff0c;外部总线和内存设备的频率并没有扩大到同样的程度。有可能实现小块的片上S…

搭建SVN服务器

简介 SVN&#xff08;Subversion&#xff09;是一种版本控制工具&#xff0c;用于管理和跟踪文件的修改历史。它可以帮助团队协作开发&#xff0c;方便地共享和更新代码&#xff0c;同时也可以提供备份和安全控制功能。 使用SVN&#xff0c;你可以创建中央代码库&#xff08;…

【MySQL】对表中数据的操作

本期给大家带来的是MySQL下对表中数据的增删查改操作 目录 一、对表插入数据 1.1 单行数据插入 1.2 多行数据插入 1.3 插入冲突时更新数据 1.4 替换式插入 1.5 插入查询结果 二、对表中数据进行查询 2.1 基本select 2.1.1 使用select查询表中数据 2.1.2 使用select…

内存快照:宕机后,Redis如何实现快速恢复?RDB

AOF的回顾 回顾Redis 的AOF的持久化机制。 Redis 避免数据丢失的 AOF 方法。这个方法的好处&#xff0c;是每次执行只需要记录操作命令&#xff0c;需要持久化的数据量不大。一般而言&#xff0c;只要你采用的不是 always 的持久化策略&#xff0c;就不会对性能造成太大影响。 …

Godot 4 源码分析 - 碰撞

碰撞功能应该是一个核心功能&#xff0c;它能自动产生相应的数据&#xff0c;比如目标对象进入、离开本对象的检测区域。 基于属性设置&#xff0c;能碰撞的都具备这样的属性&#xff1a;Layer、Mask. 在Godot 4中&#xff0c;Collision属性中的Layer和Mask属性是用于定义碰撞…