动态内存管理
一般来说,一般数据类型申请的内存是固定的,动态内存管理使得空间可以改变
知识回顾:栈区:局部变量,函数形参。堆区:动态内存管理。静态取:静态变量,全局变量
动态内存的函数
void* malloc(size_t size)函数:申请n字节连续空间,返回指向内存空间的指针。
malloc(0)未定义行为
void* free(void*p)函数:释放某地址的空间,只释放动态内存空间。
free(NULL)无影响,free(非动态内存指针)未定义
#include<stdlib.h>//malloc,free头文件
int main()
{void*p=malloc(40);//申请40个字节的空间,返回指针。申请失败返回空指针,
//40个字节空间会在程序结束时归还
free(p);//程序未结束时归还40个空间的地址
p=NULL;//free(p)后p还保存着地址,但野指针
return 0;
}
void*calloc(size_t num,size_t size)申请num个 size字节的内存空间
申请成功返回地址,失败返回空指针
int*p=(int*)calloc(10,sizeof(int));
free(p);
p=NULL;
malloc申请空间没有初始化,直接返回起始地址
calloc申请空间初始化为0
void*realloc(void*ptr,size_t size)调整动态内存空间
参数:ptr为NULL时开辟新空间,或为指向由malloc calloc realloc开辟空间的地址
size:规定空间大小
返回值:返回空间的起始地址,申请空间失败,返回空指针。用新的指针来接收地址
int*p=(int*)calloc(10,sizeof(int));
int*ptr=(int*)realloc(p,20*sizeof(int))
realloc如何修改空间
后面空间足够:直接在后面扩返回起始地址
后面不够:再找一个新空间,返回新空间的起始地址,且把旧空间释放
注意事项
对返回的指针先判断是否为空再使用
使用完记得释放空间free,并把指针赋值为空
如果使用p++操作记得先开辟变量保留原指针。
常见错误
1.对空指针解引用,对malloc,calloc,realloc的返回指针未判断直接使用。
2.对动态内存开辟空间越级访问。
3.free释放非动态内存空间的指针。
4.free释放的是动态内存空间的一部分,警惕p++,改变p的指向空间
5.free重复释放空间。
6.动态内存空间忘记释放,造成内存泄露。
柔性数组:大小自定义的数组
结构体中最后的未知大的数组
柔性数组前必须要有一个成员
结构体大小不包含柔性数组大小
含有柔性数组的结构用malloc来进行动态内存分配,开辟的空间要大于结构大小
struct S
{int n;//柔性数组前的成员
char c;
char arr[0];//表示数组大小未知
}
int main()
{struct S*ps=(struct S*ps)malloc(sizeof(struct S)+10*sizeof(char))
//柔性数组空间分配sizeof(结构体)+柔性数组空间
}
柔性数组优势:产生的空间是连续的,提高速度。方便内存释放。