c语言:2.1.3动态分配内存

上传人:ji****en 文档编号:110636732 上传时间:2019-10-30 格式:PPT 页数:63 大小:229.01KB
返回 下载 相关 举报
c语言:2.1.3动态分配内存_第1页
第1页 / 共63页
c语言:2.1.3动态分配内存_第2页
第2页 / 共63页
c语言:2.1.3动态分配内存_第3页
第3页 / 共63页
c语言:2.1.3动态分配内存_第4页
第4页 / 共63页
c语言:2.1.3动态分配内存_第5页
第5页 / 共63页
点击查看更多>>
资源描述

《c语言:2.1.3动态分配内存》由会员分享,可在线阅读,更多相关《c语言:2.1.3动态分配内存(63页珍藏版)》请在金锄头文库上搜索。

1、动态分配内存,1 动态内存分配基础 2 动态内存分配实例 3 动态内存分配进阶,本次课程大纲,Section 1:动态分配内存基础,动态分配内存概述,什么时候需要动态分配内存? 实例:顺序对一批文件进行解析,但是不知道文件的大小,如何建立缓冲区?,malloc函数,malloc函数原型: void * malloc(size_t n); n是要分配的内存的大小,返回值是分配内存的块的首地址,malloc函数,例1:使用malloc函数分配一个可以容纳10个整型元素的内存空间,并将其用作一个整型数组,malloc函数,关键代码: int * array; array = (int *)mallo

2、c(10 * 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)free函数同样是

4、一个库函数 (2)free函数的参数必须是一个由动态内存分配方法分配的内存块的首地址(使用malloc函数分配的内存),动态分配内存特点,内存空间大小可以是一个变量,其值在运行时确定 内存空间在运行时分配,在程序结束时收回;内存的分配由操作系统参与完成 动态分配的内存空间在未释放之前均可以被引用,保证其生命期,Section 2:链表,链表的概述,struct node int node; /* 数据域,存储结点的值 */ struct node * next; ;,链表示意图,value 1,value 2,value 3,value 4,NULL,处理链表使用的函数,动态申请内存:void

5、 * malloc(size_t n); 释放动态内存:void free(void *);,插入一个结点,struct node *p = /* 连接b结点和c结点 */,删除一个结点,struct node *p = /* 摘下的b结点一定要释放掉*/,Section 3:动态内存分配实例,动态内存分配实例,设计一个学生链表,其每个结点是一个学生信息的集合。每个结点包含如下信息:学生姓名、学号、C语言成绩三项。初始时拥有3个学生,添加一个学生(使用一个函数实现此操作),再删除一个学生(使用另一个函数实现此操作),并打印该学生的信息。,实例关键点分析,结点结构: struct info ch

6、ar 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; /* 正确完成操作,返回1 */ ,实例关键

7、点分析,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结尾。并将其逆序输出。 提示:作为数组的缓冲区的大小是固定的,当读取的数字的数目超过数组大小的时候需要使用realloc函数扩展缓冲区数组。,综合实例,实现一个

9、realloc函数,Section 4:动态内存分配进阶,深入理解动态分配内存的内部机制,堆和栈,代码段,数据段,环境变量和命令行参数,栈,堆,进程地址空间,malloc函数的机制,分配原则最先适合分配方法 malloc内部调用sbrk()系统调用 一个进程使用一个堆,所有内存由操作系统管理 问题:如果申请一个内存并没有释放,当进程结束运行的时候,会造成内存泄露么吗?,malloc函数的实现,内存控制块结构定义: struct mem_control_block int is_available; /* 该块是否可用 */ int size; /* 该块的大小 */ ;,malloc函数的实现

10、,两个重要的全局变量 堆底,分配块的第一块: void *managed_memory_start; 堆顶,分配块的最后一块 void *last_valid_address;,malloc代码分解,函数的参数: void *malloc(long numbytes) numbytes是要申请的字节数,但是并不包括内存控制块结构,也就是说我们实际需要的空间是numbytes + sizeof(struct mem_control_block),malloc代码分解,几个重要的局部变量: void *current_location; struct mem_control_block *curr

11、ent_location_mcb; void *memory_location;,malloc代码分解,重要的语句: numbytes = numbytes + sizeof(struct mem_control_block); /* 得到完整的需要空间,用户需要的空间 + 内存控制块结构 */ current_location = managed_memory_start; /* 从内存块队列的头开始遍历整个内存队列 */,malloc代码分解,while(current_location != last_valid_address) current_location_mcb = (stru

12、ct 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; ,malloc代码分解,如果现有的内存块不能满足需要: if(!

13、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; ,malloc代码分解,memory_location = memory_location + sizeof(struc

14、t mem_control_block); /* 返回给用户可用内存的地址,跳过内存控制块结构 */ return memory_location; /* 返回 */,sbrk系统调用,malloc代码大部分都由库来完成,为什么还要有这个系统调用? 这个系统调用做了什么? 为什么只有内存增加的时候需要系统干预? 现代操作系统的存储机制,free函数的实现,void free(void *firstbyte) struct mem_control_block *mcb; mcb = firstbyte - sizeof(struct mem_control_block); mcb-is_avai

15、lable = 1; /* 这一步是最关键的 */ return; ,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(void *)s, a, 10); s10 = 0; prin

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 电子/通信 > 综合/其它

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号