版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、.,1动态内存分配基础2动态内存分配实例3动态内存分配进阶,C语言动态分配内存,.,动态分配内存基础,.,动态分配内存概述,什么时候需要动态分配内存? 实例:顺序对一批文件进行解析,但是不知道文件的大小,如何建立缓冲区?,.,malloc函数,malloc函数原型: void * malloc(size_t n); n是要分配的内存的大小,返回值是分配内存的块的首地址,.,malloc函数,例1:使用malloc函数分配一个可以容纳10个整型元素的内存空间,并将其用作一个整型数组,.,malloc函数,关键代码: int * array; array = (int *)malloc(10 *
2、sizeof(int); 注意:内存大小不能写成数组元素的个数,.,malloc函数,例2:定义一个结构 struct test int a; char b; int c10; ; 使用malloc函数分配一个此种结构类型的对象,.,malloc函数,关键代码: struct test * p; p = (struct test *)malloc(sizeof(struct test);,.,需要注意的问题,(1)malloc函数是一个库函数,它并不是C语言中的关键字: 需要头文件才可以使用该函数 并不是所有的平台都可以使用该函数,尤其是一些单片机系统,.,需要注意的问题,(2)指针类型转换是
3、必须的,关系到接收分配好的内存块的地址可以向前看多少字节。 如果不做指针类型转换会怎么样? void * 指针存在的意义。,.,需要注意的问题,(3)内存块大小的可移植性问题 分配一个整型变量数组应使用: 数组元素个数 * sizeof(int) 确定内存块的大小 问题:sizeof和strlen函数的区别,.,free函数,free函数原型: void free(void * p); p是要释放的已分配内存的块的首地址,.,free函数,释放一块动态分配的内存: 例如: int *p; p = (int *)malloc(sizeof(int); free(p);,.,需要注意的问题,(1)
4、free函数同样是一个库函数 (2)free函数的参数必须是一个由动态内存分配方法分配的内存块的首地址(使用malloc函数分配的内存),.,动态分配内存特点,内存空间大小可以是一个变量,其值在运行时确定 内存空间在运行时分配,在程序结束时收回;内存的分配由操作系统参与完成 动态分配的内存空间在未释放之前均可以被引用,保证其生命期,.,链表,.,链表的概述,struct node int node; /* 数据域,存储结点的值 */ struct node * next; ;,.,链表示意图,value 1,value 2,value 3,value 4,NULL,.,处理链表使用的函数,动态
5、申请内存:void * malloc(size_t n); 释放动态内存:void free(void *);,.,插入一个结点,struct node *p = /* 连接b结点和c结点 */,.,删除一个结点,struct node *p = /* 摘下的b结点一定要释放掉*/,.,动态内存分配实例,.,动态内存分配实例,设计一个学生链表,其每个结点是一个学生信息的集合。每个结点包含如下信息:学生姓名、学号、C语言成绩三项。初始时拥有3个学生,添加一个学生(使用一个函数实现此操作),再删除一个学生(使用另一个函数实现此操作),并打印该学生的信息。,.,实例关键点分析,结点结构: struc
6、t info char name10; int id; int score; ; struct std struct info; struct std * next; ;,.,实例关键点分析,main函数: int main(void) /* 初始化学生链表 */ /* 插入一个学生信息结点 */ /* 删除一个学生的信息,并且打印 */ return 0; ,.,实例关键点分析,int insert(char * name, int id, int score) /* 分配一个struct std结构对象 */ /* 将参数赋值到结构对应的成员中 */ return 1; /* 正确完成操作
7、,返回1 */ ,.,实例关键点分析,int remove(int id, struct std * res) /* 根据id找到该学生的信息结点 */ /* 将该结点从链表上取下 */ /* 使用res保存该节点 */ /* 释放该结点所占用的内存 */ return 1; /* 成功操作返回1 */ ,.,综合实例,(1)实现print函数对其遍历打印链表 (2)实现destroy函数释放每一个链表节点 (3)实现search函数查找链表中的元素 (4)实现一个升级版的insert将元素按顺序插入 (5)实现一个升级版的search函数按顺序查找 (6)实现get_count函数得到链表元
8、素个数,.,综合实例,两个扩展函数: (1)实现一个链表排序函数,使用冒泡排序的方法。 (2)遍历一个链表,找到链表的中点节点。 (3)寻找某一个节点之前的那个节点,.,类malloc函数,calloc函数 void *calloc( size_t num, size_t size ); relloc函数 void *realloc(void *mem_address, unsigned int newsize);,.,综合实例,实现一个可变的数组,从一个键盘输入若干个数字,以-1结尾。并将其逆序输出。 提示:作为数组的缓冲区的大小是固定的,当读取的数字的数目超过数组大小的时候需要使用real
9、loc函数扩展缓冲区数组。,.,综合实例,实现一个realloc函数,.,动态内存分配进阶,深入理解动态分配内存的内部机制,.,堆和栈,代码段,数据段,环境变量和命令行参数,栈,堆,进程地址空间,.,malloc函数的机制,分配原则最先适合分配方法 malloc内部调用sbrk()系统调用 一个进程使用一个堆,所有内存由操作系统管理 问题:如果申请一个内存并没有释放,当进程结束运行的时候,会造成内存泄露么吗?,.,malloc函数的实现,内存控制块结构定义: structmem_control_blockintis_available; /* 该块是否可用 */intsize; /* 该块的大
10、小 */;,.,malloc函数的实现,两个重要的全局变量 堆底,分配块的第一块: void*managed_memory_start; 堆顶,分配块的最后一块void*last_valid_address;,.,malloc代码分解,函数的参数: void*malloc(longnumbytes) numbytes是要申请的字节数,但是并不包括内存控制块结构,也就是说我们实际需要的空间是numbytes + sizeof(structmem_control_block),.,malloc代码分解,几个重要的局部变量: void*current_location; structmem_cont
11、rol_block*current_location_mcb; void*memory_location;,.,malloc代码分解,重要的语句: numbytes=numbytes+sizeof(structmem_control_block); /* 得到完整的需要空间,用户需要的空间 + 内存控制块结构 */ current_location=managed_memory_start; /* 从内存块队列的头开始遍历整个内存队列 */,.,malloc代码分解,while(current_location!=last_valid_address) current_location_mcb
12、= (structmem_control_block*)current_location; if(current_location_mcb-is_available) if(current_location_mcb-size=numbytes)current_location_mcb-is_available=0; memory_location=current_location;break; current_location=current_location+ current_location_mcb-size; ,.,malloc代码分解,如果现有的内存块不能满足需要: if(!memor
13、y_location) sbrk(numbytes);memory_location=last_valid_address;last_valid_address=last_valid_address+numbytes;current_location_mcb=memory_location;current_location_mcb-is_available=0;current_location_mcb-size=numbytes;,.,malloc代码分解,memory_location=memory_location+sizeof(structmem_control_block); /* 返
14、回给用户可用内存的地址,跳过内存控制块结构 */ returnmemory_location; /* 返回 */,.,sbrk系统调用,malloc代码大部分都由库来完成,为什么还要有这个系统调用? 这个系统调用做了什么? 为什么只有内存增加的时候需要系统干预? 现代操作系统的存储机制,.,free函数的实现,voidfree(void*firstbyte) structmem_control_block*mcb; mcb=firstbyte-sizeof(structmem_control_block); mcb-is_available=1; /* 这一步是最关键的 */ return;
15、,.,free机制总结,并不是真正的释放,只是将内存块标记为可用。 问题1:释放内存后,系统显示的可用内存数会发生改变吗? 问题2:释放的内存还可以引用吗?,.,非常规使用,(1)当申请0个字节时会出现什么情况 例如: int *p; p = (int *)malloc(0); (2)释放一个非动态内存申请的空间 例如: int array10, *p; p = array; free(p);,.,两种内存分配的比较,动态分配内存和非动态分配内存的比较,.,memset函数概念,如果需要将一块内存设置为同一个值的时候,需要使用memset函数。 例如: 分配一个缓冲区,将该缓冲区内的值清零,.
16、,memset函数原形,void memset(void *s, int n, size_t size); s:需要设置内存的首地址 n:需要被设置的值 size:需要设置的字节数,.,memset函数实例,#include int main() char s10; memset(void *)s, a, 10); s10 = 0; printf(“%sn”, s); return 0; 输出结构为:aaaaaaaaa,.,综合实例,使用memset函数和malloc函数实现一个calloc函数,.,memset函数实例,#include int main() char s10; memset
17、(void *)s, a, 10); s10 = 0; printf(“%sn”, s); return 0; 输出结构为:aaaaaaaaa,.,memcpy函数概念,当需要在两块内存之间进行数据拷贝的时候需要使用memcpy函数 其原形为: void * memcpy(void *dest, const void * src, size_t n); dest:复制到目的地址 src:复制的源地址 n:需要复制的字节数,.,memcpy函数实例,#include int main() char s = “hello”, d10; memcpy(d, s, 5); d5 = 0; printf
18、(“%s”, d); return 0; 运行结果:hello,.,替代函数,void bzero(void *s, size_t n); void bcopy(void * dest, const void * src, size_t n);,.,其它内存块操作的函数,memccpy(拷贝内存内容) 定义函数 void * memccpy(void *dest, const void * src, int c,size_t n);函数说明 memccpy()用来拷贝src所指的内存内容前n个字节到dest所指的地址上。与memcpy()不同的是,memccpy()会在复制时检查参数c是否出现,若是则返回dest中值为c的下一个字节地址。返回值为0表示在src所指内存前n个字节中没有值为c的字节。,.,其它内存块操作的函数,memcmp(比较内存内容) 相关函数 bcmp,定义函数 int memcmp (const void *s1,const void *s2,size_t n);函数说明 memcmp()用来比较s1和s2所指的内存区间前n个字符。字符串大小的比较是以ASCII码表上的顺序来决定,次顺序
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 证券行业2025年三季报综述:业绩同环比高增景气持续回升
- 2025年根河市人民政府面向社会公开招聘(补招)乡镇及政府专职消防队员26人备考题库及1套完整答案详解
- 2025年德州市武城县人民医院合同制医师长期招聘12人备考题库及1套完整答案详解
- 四川省公安厅所属事业单位招聘考试真题2024
- 2025新疆北屯额河明珠国有资本投资有限公司招聘2人参考考试试题及答案解析
- matlab课程设计与应用答案
- 2026年江西铜业技术研究院有限公司北京分院院长招聘1人考试重点试题及答案解析
- 宜宾市南溪区事业单位2025年公开考核招聘高层次和急需紧缺专业人才考试重点题库及答案解析
- 2025年直播电商供应链全球化趋势报告
- 中化地质矿山总局地质研究院2026年高校应届毕业生招聘备考题库及1套完整答案详解
- 工业软件基础知识培训课件
- 山地光伏150MW技术标(EPC)方案投标文件(技术方案)
- 儿童自身炎症性疾病诊断与治疗专家共识解读
- T/CCPITCSC 096-2022名表真假鉴定规范
- 皮肤恶性肿瘤课件
- 2025人教版七年级下册英语寒假预习重点语法知识点清单
- CWAN 0020-2022 机器人焊接技能竞赛团体标准
- 浙江省温州市2023-2024学年六年级上学期期末科学试卷(含答案)1
- 中国文化:复兴古典 同济天下学习通超星期末考试答案章节答案2024年
- 《底层逻辑》刘润
- T-NMAAA.0002-2021 营运机动车停运损失鉴定评估规范
评论
0/150
提交评论