动态内存管理是我们高效利用内存空间的方式,主要操作有开辟空间,扩充空间,释放空间。这些操作都需要头文件<stdlib.h>。
1.开辟空间
使用malloc函数可以在堆区中申请一块连续可用的空间。
void* malloc(size_t size) //原型
//申请大小为size个字节的空间,申请成功返回这块空间的起始地址,否则返回NULL
为防止出错,我们要检验是否申请成功。
int* p = (int*)malloc(sizeof(int)*10);
//返回值类型是void*,要强制类型转换
if (p == NULL)
{
perror("malloc"); //返回分配过程中的错误
return 1; //直接结束程序,避免使用时出错
}
calloc同样能向内存申请空间,申请方式略有不同。
void* calloc(int num,size_t size) //原型
//申请num个大小为size的空间
用malloc申请的空间不初始化,而用calloc申请的空间初始为0。
2.释放空间
当我们住酒店时,会先订房,住了之后退房。内存申请也是一样,申请之后不用了也要归还,称为释放空间。用free完成释放空间的操作。
free(要释放空间的指针);
释放过后空间内的数据都会销毁,无法再使用。指针也会变成野指针,应手动置为空指针防止提升安全性。
free(p);
p = NULL;
程序执行结束后,计算机会统一回收空间,但若是程序很久不结束,空间会一直处于浪费状态。堆区空间基本都是碎片空间,碎片积累过多,会影响到程序性能。所以我们不再用某块空间时,应尽快释放空间。
3.扩容空间
当空间不够用时,我们可以使用realloc扩容空间。
void* realloc(void* ptr,size_t size) //原型
//ptr是要调整的内存地址
//size是调整之后的新大小,单位是字节,返回新地址
若旧空间大小不够,会找到新的大小足够的空间,把原数据拷贝到新空间,返回新地址,释放原来空间。大多数情况下都是返回新地址。
同样,对于realloc,我们也要检测返回是否为NULL。
int* p = (int*)malloc(sizeof(int)*10);
if (p1 == NULL)
{
perror("malloc");
return 1;
}
int* p1 = (int*)realloc(p,sizeof(int)*15);
if (p1 == NULL)
{
perror("realloc"); //返回重新分配过程中的错误
free(p); //释放原空间内存
return 1; //直接结束程序,避免使用时出错
}
p = p1; //将新地址赋给原指针
p1 = NULL; //临时地址置空
接下来是一个读取并储存n个数的程序。
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n;
scanf("%d", &n);
int* p = (int*)malloc(sizeof(int) * n);
if (p == NULL)
{
perror("malloc");
return 1;
}
int i;
for (i = 0; i < n; i++)
{
scanf("%d", &p[i]);
}
for (i = 0; i < n; i++)
{
printf("%d ", p[i]);
}
free(p);
p = NULL;
return 0;
}



