为什么存在动态内存分配?
我们当前已有的内存分配可能不能满足我们的需求,它有自己的局限性,比如:
int main()
{
int arr[10];
//我们向内存申请了40个字节的空间,这片空间开辟好了之后,大小就固定死了,
//不能变大变小,这是它的局限性,假设我要存放41个字节的数据,那空间就不够了,
//再假设我只是要存放1个字节的数据,那么多余的空间就浪费了,这样就不够灵活。
return 0;
}
这时候就需要用到我们的动态内存函数:
提示:以下是本篇文章正文内容,下面案例可供参考
void * malloc (size_t size);
这个函数向内存申请一块连续可用的空间,并返回指向该空间的指针。
1.如果开辟成功,则返回一个指向开辟好空间的指针。
2.如果开辟失败,则返回一个NULL指针,因此malloc的返回值一定要做检查。
3.返回值的类型是 void* ,所以malloc函数并不知道开辟空间的类型,具体在使用的时候使用者自己来决定
void free ( void * ptr );
free函数是用来释放动态开辟的内存
1.如果参数ptr指向的空间不是动态开辟的,那free函数的行为是未定义的。
2.如果参数ptr是NULL指针,则函数什么都不做。
#include
int main()
{
//int arr[10];
//动态开辟
int* p = (int*)malloc(40);
int* ptr = p;//把初始位置保存下来
if (ptr == NULL) //判断开辟成功还是失败
{
return 1;
}
//使用
int i = 0;
for (i = 0; i < 10; i++)
{
*ptr = i;
ptr++;
}
//释放
free(p);
p = NULL;//置为空指针
return 0;
}
void* calloc (size_t num, size_t size);
1.函数的功能是为 num 个大小为 size 的元素开辟一块空间,并且把空间的每个字节初始化为0。
2.与函数 malloc 的区别只在于 calloc 会在返回地址之前把申请的空间的每个字节初始化为全0。
int main()
{
//int arr[10];
//动态开辟
int* p = (int*)calloc(10,sizeof(int));
int* ptr = p;//把初始位置保存下来
if (ptr == NULL) //判断开辟成功还是失败
{
return 1;
}
//使用
int i = 0;
for (i = 0; i < 10; i++)
{
*ptr = i;
ptr++;
}
//释放
free(p);
p = NULL;//置为空指针
return 0;
}
void* realloc (void* ptr, size_t size);
realloc函数的出现让动态内存管理更加灵活。
有时会我们发现过去申请的空间太小了,有时候我们又会觉得申请的空间过大了,那为了合理的时 候内存,我们一定会对内存的大小做灵活的调整。
那 realloc 函数就可以做到对动态开辟内存大小 的调整。
#include
int main()
{
//int arr[10];
//动态开辟
int* p = (int*)calloc(10,sizeof(int));
if (p == NULL) //判断开辟成功还是失败
{
return 1;
}
//使用
int i = 0;
for (i = 0; i < 10; i++)
{
*(p+i) = i;
}
//增容
int* ptr = (int*)realloc(p, 80);
//注意这里一定要判断释放增容成功
if (ptr != NULL)
{
p = ptr;
}
//使用
// ......
//释放
free(p);
p = NULL;//置为空指针
return 0;
}
接下来用刚刚学到的函数改造一下静态通讯录:
//头文件
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include
#define NAME 10
#define SEX 6
#define TELE 12
#define ADDR 10
#define NUM1 3
#define NUM2 2
//表示人的信息
struct peoinfo
{
char name[NAME];
char sex[SEX];
int age;
char tele[TELE];
char addr[ADDR];
};
//通讯录
struct contact
{
struct peoinfo *data;//一千个人的信息
int sz;//下标记录
int sum;//容量计数
};
//初始化通讯录
void initcontact(struct contact* p);
//添加联系人
void addcontact(struct contact* p);
//显示通讯录
void showcontact(struct contact* p);
//删除联系人
void delcontact(struct contact* p);
//搜索联系人
void searchcontact(struct contact* p);
//清空通讯录
void emptycontact(struct contact* p);
//按照年龄排序通讯录
void sortcontact(struct contact* p);
//销毁通讯录
void quitcontact(struct contact* p);
//修改通讯录指定联系人
void modifcontact(struct contact* p);
//主函数
void menu()
{
printf("*****1.Add 2.del********\n");
printf("*****3.search 4.modif******\n");
printf("*****5.show 6.empty******\n");
printf("*****7.sort 0.exit*******\n");
printf("******************************\n");
}
int main()
{
int input = 0;
//创建通讯录
struct contact con;
//初始化通讯录
initcontact(&con);
do
{
menu();
printf("请选择>:\n");
scanf("%d", &input);
switch (input)
{
case 0:
quitcontact(&con);
break;
case 1:
addcontact(&con);
break;
case 2:
delcontact(&con);
break;
case 3:
searchcontact(&con);
break;
case 4:
modifcontact(&con);
break;
case 5:
showcontact(&con);
break;
case 6:
emptycontact(&con);
break;
case 7:
sortcontact(&con);
break;
default:
printf("选择错误\n");
break;
}
} while (input);
return 0;
}
//函数的实现
//初始化通讯录
void initcontact(struct contact* p)
{
assert(p);
//初始化开辟三个人信息的容量
p->data=(struct peoinfo*)malloc(NUM1 * sizeof(struct peoinfo));
if (p->data == NULL) //判断是否开辟成功
{
return;
}
p->sz = 0;
p->sum = NUM1;//初始化为3个人的信息的容量
}
//添加联系人
void addcontact(struct contact* p)
{
assert(p);
if (p->sz == p->sum)
{
printf("通讯录已满\n");
//空间满了,使用realloc函数扩容
struct peoinfo*ptr =(struct peoinfo*)realloc(p->data, (p->sum+NUM2) * sizeof(struct peoinfo));
if (ptr == NULL)
{
return;
}
p->data = ptr;
p->sum += NUM2;//对应的容量也要增加
printf("扩容成功\n");
}
printf("请输入名字:>");
scanf("%s", p->data[p->sz].name);
printf("请输入性别:>");
scanf("%s", p->data[p->sz].sex);
printf("请输入年龄:>");
scanf("%d", &p->data[p->sz].age);
printf("请输入电话:>");
scanf("%s", p->data[p->sz].tele);
printf("请输入住址:>");
scanf("%s", p->data[p->sz].addr);
printf("添加联系人成功\n");
p->sz++;
}
//显示通讯录
void showcontact(struct contact* p)
{
assert(p);
printf("%-20s\t%-5s\t%-5s\t%-12s\t%-30s\n", "姓名", "性别", "年龄", "电话", "地址");
int i = 0;
for (i = 0; i < p->sz; i++)
{
printf("%-20s\t", p->data[i].name);
printf("%-5s\t", p->data[i].sex);
printf("%-5d\t", p->data[i].age);
printf("%-12s\t", p->data[i].tele);
printf("%-30s\t", p->data[i].addr);
printf("\n");
}
}
int findname(struct contact* p, char name[])
{
assert(p);
int i = 0;
for (i = 0; i < p->sz; i++)
{
if (strcmp(name, p->data[i].name) == 0)
{
return i;
}
}
return -1;
}
//删除联系人
void delcontact(struct contact* p)
{
assert(p);
printf("请输入要删除人的姓名\n");
char name[20];
scanf("%s", name);
int ret = findname(p, name);
if (ret == -1)
{
printf("该联系人不存在\n");
}
else
{
int i = 0;
for (i = ret; i < p->sz - 1; i++)
{
p->data[i] = p->data[i + 1];
}
printf("成功删除联系人\n");
p->sz--;
}
}
//搜索联系人
void searchcontact(struct contact* p)
{
assert(p);
printf("请输入要搜索人的姓名:>\n");
char name[20];
scanf("%s", name);
int ret = findname(p, name);
if (ret == -1)
{
printf("该联系人不存在\n");
}
else
{
printf("%-20s\t", p->data[ret].name);
printf("%-5s\t", p->data[ret].sex);
printf("%-5d\t", p->data[ret].age);
printf("%-12s\t", p->data[ret].tele);
printf("%-30s\t", p->data[ret].addr);
printf("\n");
}
}
//清空通讯录
void emptycontact(struct contact* p)
{
assert(p);
memset(p->data, 0, p->sz * sizeof(struct peoinfo));
p->sz = 0;
//释放内存,指针置为NULL
free(p->data);
p->data = NULL;
printf("已清空通讯录\n");
}
//排序通讯录
int cmp(const void* e1, const void* e2)
{
return ((struct peoinfo*)e1)->age - ((struct peoinfo*)e2)->age;
}
void sortcontact(struct contact* p)
{
assert(p);
qsort(p->data, p->sz, sizeof(struct peoinfo), cmp);
}
//退出通讯录,并释放内存。
void quitcontact(struct contact* p)
{
assert(p);
free(p->data);
p->data = NULL;
printf("退出游戏\n");
}
//修改通讯录指定联系人
void modifcontact(struct contact* p)
{
assert(p);
printf("请输入联系人名字;>\n");
char name[20];
scanf("%s", &name);
int ret = findname(p, name);
if (ret == -1)
{
printf("没有该联系人\n");
}
else
{
printf("请输入名字:>");
scanf("%s", p->data[ret].name);
printf("请输入性别:>");
scanf("%s", p->data[ret].sex);
printf("请输入年龄:>");
scanf("%d", &p->data[ret].age);
printf("请输入电话:>");
scanf("%s", p->data[ret].tele);
printf("请输入住址:>");
scanf("%s", p->data[ret].addr);
printf("修改成功\n");
}
}