第17部分动态存储空间管理与链表
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
用户结构体指针数组 数组长度 用户号
n 将指定用户号的用户删除,返回该用户原来所在位置
int DeleteAccountByNumber(struct UserAccount *Accounts[], int nLen, char *pszUserNO)
{
int i;
for (i = 0; i < nLen; i++) //找到指定用户
n 为保证动态存储的有效使用,动态分配块不再用 时应释放。动态存储块的释放只能通过调用free完 成。Memory leak
n 函数原型
n void free(void *p);
n 功能
n free释放p指的存储块。
n 注意
n 该块必须是通过动态存储分配得到的,不要对并非指向 动态分配块的指针用本操作
功能示例
Accounts
新找到的空位 长度为50
0x0012ff6d N0UxL0L012ff30 0x0012ff80 0x0012ce00 0x0012fe12
…
0x0012ff6d 0x0012ff30 0x0012ff80
0x0012ce00 0x0012fe12
08120001 08120100 08120002
n 解决的办法是“动态存储分配”。在程序运行中 做存储分配工作。
2020/11/25
第17部分动态存储空间管理与链表
3. 动态存储分配
n 动态存储分配
n 根据运行中的需要分配存储,取得存储块使 用,称为动态存储分配。在运行中根据需要 动态进行。
n 动态存储块具有起始地址,地址可以存 储在指针里,因此可以借助于指针保存 存储空间地址。
void InitAccounts(struct UserAccount *Accounts[], int nLen) {
for (int i = 0; i < nLen; i++) Accounts[i] = NULL;
} n 寻找一个空位置返回,-1表示无空位置
int FindEmptyPlace(struct UserAccount *Accounts[], int nLen)
n 用指针指向存储块,间接使用被指存储。 访问动态分配存储是指针的最重要用途。
2020/11/25
第17部分动态存储空间管理与链表
4. 动态存储释放及存储堆
n 动态释放
n 不用的动态存储块应交还系统,动态申请的内 存空间必须由程序代码以显式的方式主动释放。
n 动态分配、释放由动态存储管理系统完成, 这是程序运行系统的子系统,管理着称作 堆(英文heap)的存储区。
例如
n 设一个班最多有50人,但每个班的人数不定,为了 表示这50用户,可以定义如下指针数组
n struct UserAccount *Accounts [50]; n 完成如下功能
n 初始化指针数组 n 将新生成的某个班用户加入班级用户集,并存放
在空位置上。 n 将某个班指定用户号的用户删除 n 给某个班所有女生发m元补助 n 将新生成的某个班用户插入到指定位置i上,i后面
第17部分动态存储空间 管理与链表
2020/11/25
第17部分动态存储空间管理与链表
一、动态存储分配及常见函数说明
隐式和显式
2020/11/25
第17部分动态存储空间管理与链表
1. 引例
n 要处理学生成绩,需要用数组存放。但 编程时并不知道运行时需要处理多少学 生成绩,每次处理的成绩项数也可能不 同。
n 新块小时保存原块n范围内数据; n 新块大时原数据存在,新增部分不初始化。分配成功后
原块可能改变。
n 无法满足时返回空指针,原块不变。
n 常用写法(防止分配失败导致原存储块丢失) :
n q = (double*)realloc(p, m * sizeof(double)); n if (q == NULL) { /*未成功,p仍指原块,特殊处理*/ } n else { p = q; /* 令p指向新块,正常处理 */ ...
}
}
return -1;
}
2020/11/25
第17部分动态存储空间管理与链表
删除功能示例
Accounts
把孙悟空位置找到
0x0012ff6d 0x00N1U2LffL30 0x0012ff80 0x0012ce00 0x0012fe12
…
0x0012ff6d 0x0012ff30 0x0012ff80
08120007
08120099
张帅帅
孙悟空
赵小飞
罗小花
李美美
…
110108… M 0.10
110105… M 600.10
新结点
360108… M 20.00
410108… F 88.20
孙悟空报到
350108… F 500.00
2020/11/25
第17部分动态存储空间管理与链表
功能实现(续)
{ Accounts[i]->dBalance+= dAmount; nCounter++;
} } return nCounter; } ChargeByGender(Accounts, 50, ‘F’, 10.0);//妇女节发补助
把孙悟空开除:
释放存储空间
DeleteAccountByNumber(Accounts, 50, “08120100”)
2020/11/25
第17部分动态存储空间管理与链表
功能实现(续)
n 给指定性别的群体充值,返回充值人数 int ChargeByGender(struct UserAccount *Accounts[], int nLen, char
int nPlace; if ((nPlace = FindEmptyPlace(Accounts, nLen)) == -1)
return -1; Accounts[nPlace] = pUser; //完成放置操作 return nPlace; //返回位置 }
Baidu Nhomakorabea
2020/11/25
第17部分动态存储空间管理与链表
n 无法分配时返回空指针值。前面的存储分配问题 也可用下面语句实现
n data = (double*)calloc(n, sizeof(double));
n 主要差别
n malloc对所分配的区域不做任何事情,calloc对整个区
域自动清0。
2020/11/25
第17部分动态存储空间管理与链表
7. 空间释放函数:free
2020/11/25
第17部分动态存储空间管理与链表
6. calloc
n 带计数和清0的存储分配函数calloc,原型:
n void *calloc(size_t n, size_t size); n size是元素大小,n是个数。
n 分配一块存储,足够存n个大小为size的元素,并 把元素全部清0;
{ … } //可以有不同的搜索策略
NULL NULL
…
2020/11/25
第17部分动态存储空间管理与链表
功能实现(续)
n 将新用户放在空位置上,不成功返回-1,成功返回位置号 int AddNewAccountAtAnyEmptyPlace(struct UserAccount
*Accounts[], int nLen, struct UserAccount *pUser) {
n 大部分常规语言都有这种机制。
2020/11/25
第17部分动态存储空间管理与链表
5. C语言的动态存储管理机制
n 用标准库函数实现
n stdlib.h n malloc.h
n 存储分配函数malloc(),原型:
n void *malloc(size_t n); /*size_t是某整型*/
n 功能
的用户顺序往后退。
2020/11/25
第17部分动态存储空间管理与链表
指针数组结构示例
Accounts
空指针,可能 长度为50
曾被删除
后续元素或空 或不空
0x0012ff6d NULL 0x0012ff80 0x0012ce00 0x0012fe12
…
0x0012ff6d 08120001 张帅帅 110108… M 0.10
n int *pnarr[10]; //定义一个长度为10的整型指针 数组(整型地址数组)
n char *psz[5]; //定义一个长度为5的字符指针数 组。
0x0012ff7d 0x0012ff80 …
0x0012fe12
其中每个元素都用来保存某种类型的存储空间的地址
2020/11/25
第17部分动态存储空间管理与链表
2020/11/25
第17部分动态存储空间管理与链表
malloc说明
n malloc使用注意事项:
n 的返回值(void*)应通过类型强制转为特定 指针类型后赋给指针变量。
n 分配存储块大小应该用sizeof计算 n 动态分配必须检查成功与否 n 动态分配的块大小也是确定的。越界使用(尤
其是越界赋值)是严重错误,可能导致程序或 系统垮台
n int n; n ... n scanf("%d", &n); n double scores[n]; /* 不行!*/ n ... /* 读入数据,然后处理 */ n 不能用变量说明scores大小(必须静态确定)。
2020/11/25
第17部分动态存储空间管理与链表
2. 问题的本质及解决方案
0x0012ff80
0x0012ce00 0x0012fe12
08120002
08120007
08120099
赵小飞
罗小花
李美美
…
360108… M 20.00
410108… F 88.20
350108… F 500.00
2020/11/25
第17部分动态存储空间管理与链表
功能实现
n 初始化指针数组
n 问题的本质
n 程序运行中需要使用存储,有时程序对存储的需求量在 写程序时不能确定。
n 可能解决方案
1)分析问题,定义适当大小的数组。若分析正确,一般 都能处理。但数据很多时程序就不能用。
2)定义尽可能大的数组以满足任何需要。浪费大量存储 资源。如有多个这种数组就更难办。系统可能无法容纳 几个大数组,但实际上它们并不同时需要很大空间。
n 分配一块不小于n的存储,返回其地址。无法 满足时返回空指针值。
2020/11/25
第17部分动态存储空间管理与链表
例
int n; double *data; ... scanf("%d", &n); data=(double*)malloc(n*sizeof(double)); if (data == NULL) { .... /* 分配未完成时的处理 */ } ..data[i]..*(data+j)../*正常处理*/
n p值为空时什么也不做 n 执行free(p)后p值未变,被指块可能已变。不允许再间
接访问已释放存储块
2020/11/25
第17部分动态存储空间管理与链表
8. 分配调整函数realloc
n 函数原型
n void *realloc(void *p, size_t n);
n 功能
n 更改已有分配。p指原分配块,n是新大小要求。 n 返回大小至少为n的存储块指针,新块与原块一致:
0x0012ce00 0x0012fe12
08120001 08120100 08120002
08120007
08120099
张帅帅
孙悟空
赵小飞
罗小花
李美美
…
110108… M 0.10
110105… M 600.10
360108… M 20.00
410108… F 88.20
350108… F 500.00
cGender, double dAmount) {
int nCounter = 0; //计数器 for (int i = 0; i < nLen; i++)//遍历所有的用户 {
if ((NULL != Accounts[i]) && (Accounts[i]->cGender == cGender))
{
if ((Accounts[i] != NULL) &&
字符串比 较函数
(strcmp(pszUserNO, Accounts[i]->szUserNO) == 0)) {
free(Accounts[i]); //释放空间
Accounts[i] = NULL; //将当前位置置空
return i;
2020/11/25
第17部分动态存储空间管理与链表
二、动态存储空间管理
如果动态申请了许多同类型缓冲区, 该如何管理?
2020/11/25
第17部分动态存储空间管理与链表
方法1:指针数组(地址数组)
n 设置一段内存空间,例如数组,用来保存存储空 间的起始地址。
n 数组中每个元素用来保存某种类型的存储空间的 地址,等于每个元素都是一个指针变量。