版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1动态内存分配基础
2动态内存分配实例
3动态内存分配进阶
C语言动态分配内存2021/5/91动态分配内存基础2021/5/92
动态分配内存概述什么时候需要动态分配内存?实例:顺序对一批文件进行解析,但是不知道文件的大小,如何建立缓冲区?2021/5/93 malloc函数 malloc函数原型:
void*malloc(size_tn); n是要分配的内存的大小,返回值是分配内存的块的首地址2021/5/94 malloc函数
例1:使用malloc函数分配一个可以容纳10个整型元素的内存空间,并将其用作一个整型数组2021/5/95 malloc函数
关键代码:
int*array; array=(int*)malloc(10*sizeof(int));
注意:内存大小不能写成数组元素的个数2021/5/96 malloc函数
例2:定义一个结构
structtest{ inta; charb; intc[10]; };
使用malloc函数分配一个此种结构类型的对象2021/5/97 malloc函数
关键代码:
structtest*p; p=(structtest*)malloc(sizeof(structtest));2021/5/98
需要注意的问题(1)malloc函数是一个库函数,它并不是C语言中的关键字:需要头文件<stdlib.h>才可以使用该函数并不是所有的平台都可以使用该函数,尤其是一些单片机系统2021/5/99
需要注意的问题(2)指针类型转换是必须的,关系到接收分配好的内存块的地址可以向前看多少字节。如果不做指针类型转换会怎么样?void*指针存在的意义。2021/5/910
需要注意的问题(3)内存块大小的可移植性问题分配一个整型变量数组应使用: 数组元素个数*sizeof(int)
确定内存块的大小 问题:sizeof和strlen函数的区别2021/5/911 free函数 free函数原型:
voidfree(void*p); p是要释放的已分配内存的块的首地址2021/5/912 free函数
释放一块动态分配的内存: 例如:
int*p; p=(int*)malloc(sizeof(int)); free(p);2021/5/913
需要注意的问题(1)free函数同样是一个库函数(2)free函数的参数必须是一个由动态内存分配方法分配的内存块的首地址(使用malloc函数分配的内存)2021/5/914
动态分配内存特点内存空间大小可以是一个变量,其值在运行时确定内存空间在运行时分配,在程序结束时收回;内存的分配由操作系统参与完成动态分配的内存空间在未释放之前均可以被引用,保证其生命期2021/5/915链表2021/5/916
链表的概述structnode{ intnode;/*数据域,存储结点的值*/ structnode*next;};2021/5/917
链表示意图value1value2value3value4NULL2021/5/918
处理链表使用的函数动态申请内存:void*malloc(size_tn);释放动态内存:voidfree(void*);2021/5/919
插入一个结点 structnode*p=&b; a.next=p;/*连接a结点和b结点*/ b.next=&c;/*连接b结点和c结点*/2021/5/920
删除一个结点 structnode*p=&b; a.next=b.next;/*连接a结点和c结点*/ free(p);/*摘下的b结点一定要释放掉*/2021/5/921动态内存分配实例2021/5/922
动态内存分配实例
设计一个学生链表,其每个结点是一个学生信息的集合。每个结点包含如下信息:学生姓名、学号、C语言成绩三项。初始时拥有3个学生,添加一个学生(使用一个函数实现此操作),再删除一个学生(使用另一个函数实现此操作),并打印该学生的信息。2021/5/923
实例关键点分析
结点结构:
structinfo{ charname[10]; intid; intscore; }; structstd{ structinfo; structstd*next; };2021/5/924
实例关键点分析 main函数: intmain(void) { /*初始化学生链表*/ /*插入一个学生信息结点*/ /*删除一个学生的信息,并且打印*/ return0; }2021/5/925
实例关键点分析 intinsert(char*name,intid,intscore) { /*分配一个structstd结构对象*/ /*将参数赋值到结构对应的成员中*/ return1;/*正确完成操作,返回1*/ }2021/5/926
实例关键点分析 intremove(intid,structstd**res) { /*根据id找到该学生的信息结点*/ /*将该结点从链表上取下*/ /*使用res保存该节点*/ /*释放该结点所占用的内存*/ return1;/*成功操作返回1*/ }2021/5/927
综合实例
(1)实现print函数对其遍历打印链表 (2)实现destroy函数释放每一个链表节点 (3)实现search函数查找链表中的元素 (4)实现一个升级版的insert将元素按顺序插入 (5)实现一个升级版的search函数按顺序查找 (6)实现get_count函数得到链表元素个数2021/5/928
综合实例
两个扩展函数:(1)实现一个链表排序函数,使用冒泡排序的方法。(2)遍历一个链表,找到链表的中点节点。(3)寻找某一个节点之前的那个节点2021/5/929
类malloc函数calloc函数
void*calloc(size_tnum,size_tsize);relloc函数
void*realloc(void*mem_address,unsignedintnewsize);2021/5/930
综合实例
实现一个可变的数组,从一个键盘输入若干个数字,以-1结尾。并将其逆序输出。 提示:作为数组的缓冲区的大小是固定的,当读取的数字的数目超过数组大小的时候需要使用realloc函数扩展缓冲区数组。2021/5/931
综合实例
实现一个realloc函数2021/5/932动态内存分配进阶深入理解动态分配内存的内部机制2021/5/933
堆和栈代码段数据段环境变量和命令行参数栈堆进程地址空间2021/5/934 malloc函数的机制分配原则——最先适合分配方法malloc内部调用sbrk()系统调用一个进程使用一个堆,所有内存由操作系统管理
问题:如果申请一个内存并没有释放,当进程结束运行的时候,会造成内存泄露么吗?2021/5/935 malloc函数的实现
内存控制块结构定义:
struct
mem_control_block
{
int
is_available;/*该块是否可用*/
int
size;/*该块的大小*/
};2021/5/936 malloc函数的实现
两个重要的全局变量 堆底,分配块的第一块:
void
*managed_memory_start;
堆顶,分配块的最后一块
void
*last_valid_address;2021/5/937 malloc代码分解
函数的参数:
void
*malloc(long
numbytes)
{
…… } numbytes是要申请的字节数,但是并不包括内存控制块结构,也就是说我们实际需要的空间是numbytes+sizeof(struct
mem_control_block)2021/5/938 malloc代码分解
几个重要的局部变量:
void
*current_location;
struct
mem_control_block
*current_location_mcb;
void
*memory_location;
2021/5/939 malloc代码分解
重要的语句:
numbytes
=
numbytes
+
sizeof(struct
mem_control_block);/*得到完整的需要空间,用户需要的空间+内存控制块结构*/
current_location
=
managed_memory_start;/*从内存块队列的头开始遍历整个内存队列*/
2021/5/940 malloc代码分解while(current_location
!=
last_valid_address){ current_location_mcb
=(struct
mem_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;}
2021/5/941 malloc代码分解
如果现有的内存块不能满足需要:
if(!
memory_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;
}
2021/5/942 malloc代码分解
memory_location
=
memory_location
+
sizeof(struct
mem_control_block);/*返回给用户可用内存的地址,跳过内存控制块结构*/
return
memory_location;/*返回*/
2021/5/943 sbrk系统调用malloc代码大部分都由库来完成,为什么还要有这个系统调用?这个系统调用做了什么?为什么只有内存增加的时候需要系统干预?现代操作系统的存储机制2021/5/944 free函数的实现void
free(void
*firstbyte)
{ struct
mem_control_block
*mcb;
mcb
=
firstbyte
-
sizeof(struct
mem_control_block);
mcb->is_available
=
1;/*这一步是最关键的*/ return;}2021/5/945 free机制总结
并不是真正的释放,只是将内存块标记为可用。 问题1:释放内存后,系统显示的可用内存数会发生改变吗? 问题2:释放的内存还可以引用吗?2021/5/946
非常规使用(1)当申请0个字节时会出现什么情况例如:int*p;p=(int*)malloc(0);(2)释放一个非动态内存申请的空间例如:intarray[10],*p;p=array;free(p);2021/5/947
两种内存分配的比较动态分配内存和非动态分配内存的比较动态分配内存非动态分配内存大小在编译时确定大小在运行时确定由编译器分配由操作系统参与分配分配在数据段和栈内在堆内由操作系统自动释放手动显式释放2021/5/948 memset函数概念
如果需要将一块内存设置为同一个值的时候,需要使用memset函数。
例如: 分配一个缓冲区,将该缓冲区内的值清零2021/5/949 memset函数原形voidmemset(void*s,intn,size_tsize);s:需要设置内存的首地址n:需要被设置的值size:需要设置的字节数2021/5/950 memset函数实例#include<stdio.h>intmain(){ chars[10]; memset((void*)s,‘a’,10); s[10]=‘\0’; printf(“%s\n”,s); return0;}输出结构为:aaaaaaaaa2021/5/951
综合实例
使用memset函数和malloc函数实现一个calloc函数2021/5/952 memset函数实例#include<stdio.h>intmain(){ chars[10]; memset((void*)s,‘a’,10); s[10]=‘\0’; printf(“%s\n”,s); return0;}输出结构为:aaaaaaaaa2021/5/953 memcpy函数概念
当需要在两块内存之间进行数据拷贝的时候需要使用memcpy函数 其原形为:
void*memcpy(void*dest,constvoid*src,size_tn); dest:复制到目的地址
src:复制的源地址
n:需要复制的字节数2021/5/954 memcpy函数实例#include<stdio.h>intmain(){ chars[]=“hello”,d[10]; memcpy(d,s,5); d[5]=‘\0’; printf(“%s”,d); return0;}运行结果:hello2021/5/955
替代函数voidbzero(void*s,size_tn);voidbcopy(void*dest,constvoid*src,size_tn);2021/5/956
其它内存块操作的函数 memccpy(拷贝内存内容) 定义函数void*memccpy(void*dest,constvoid*src,intc,size_tn);
函数说明memccpy()用来拷贝src所指的内存内容前n个字节到dest所指的地址上。与memcpy()不同的是,memccpy()会在复制时检查参数c是否出现,若是则返回dest中值为c的下一个字节地址。
返回值为0表示在src所指内存前n个字节中没有值为c的字节。
2021/5/957
其它内存块操作的函数 memcmp(比较内存内容)相关函数bcmp,
定义函数intmemcmp(constvoid*s1,constvoid*s2,size_tn);
函数说明memcmp()用来比较s1和s2所指的内存区间前n个字符。字符串大小的比较是以ASCII码表上的顺序来决定,次顺序亦为字符的值。memcmp()首先将s1第一个字符值减去s2第一个字符的值,若差为
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 航运行业保安工作总结
- 北京市安全管理工作总结
- 银行工作总结团结合作追求卓越
- 2023-2024学年北京市101中学高一(下)期中语文试卷
- 家具行业招聘成功案例
- 娱乐设施行业推广计划总结
- 医疗话务员工作总结
- 医学美容诊所前台工作总结
- 2024年认识安全标志的教案
- 凉亭制定安装协议书(2篇)
- 消防设施安全检查表
- 钻孔灌注桩施工方案 (详细)
- 新建南通至宁波高速铁路站前Ⅲ标二分部出海栈桥及综合码头(自用)工程海域使用论证报告表
- 车身稳定系统课件
- 2023-2024学年广东省东莞市七年级上期末数学试卷附答案
- 检察机关的体制与组织机构课件
- 山东省潍坊市潍城区2023-2024学年六年级上学期期末语文试题
- 2024年1月四川高中学业水平合格考物理试卷试题真题
- 30题产业研究员岗位常见面试问题含HR问题考察点及参考回答
- 农村电商公共服务体系的建设与完善研究-以XX村为例
- 复合机器人行业分析
评论
0/150
提交评论