malloc函数(堆区)
1.调用形式:
? ? ? ? void* malloc(size_t size)
功能为向内存申请一块连续可用的空间并返回指向空间的指针
2.成功与失败:成功则返回指向开辟空间的指针,失败则返回空指针,因此此函数的返回值必须做检查
3.返回指针为void类型,所以使用时由使用者自己决定
4.如果size为0则malloc的行为是标准未定义的,取决于编译器
int *p=(int*)malloc(40);
int i=0;
for(i=0;i<1;i++)
{
*p=i;
p++;
}
必须对返回值进行判断,否则可能是空指针
free函数
1.调用形式:void free(void*ptr)
功能为释放回收动态开辟的内存
2.如果指针指向的内存不是动态开辟的,则free函数的行为是未定义的
3.如果指针为NULL则函数什么都不做
4.与malloc一样都声明在stdio.h头文件中
//接上malloc的代码演示
free(p);
p=NULL;//避免成为野指针
calloc函数
1.调用形式:void* calloc(size_t num,size_t size)
功能为将num个大小为size的元素开辟一段空间,并且将空间的每个字节初始化为0,这是与malloc函数唯一的区别
realloc函数
1.调用形式:void*realloc(void*ptr,size_t size)
ptr是要调整内存的地址,size是调整之后的大小,返回值为调整之后内存的起始位置
2.调整空间失败会返回空指针,调整成功有两种情况,一种是扩容后会与其他已有的内存空间相冲突,此函数会在内存的堆区中重新找一个符合要求的空间,将旧空间的内容拷贝到新空间中,并释放旧空间,再返回新空间的指针,另一种是有足够的空间,就直接扩大,返回旧空间的起始地址
3.返回的指针一般不用调整空间的指针接收,防止变为空指针,需要使用if进行判断和操作
4.如何实现malloc的功能?realloc(NULL,size_t size)
以上几个函数释放的空间,如果不使用free释放则不会自动释放,否则只能等到程序结束由操作系统释放
常见错误:对非动态内存空间进行释放,释放的动态内存空间不完整,如释放移动过的指针,或者多次释放一块动态内存,或者忘了释放动态内存导致内存泄漏
此处错误的原因:str作为形参赋值给了p,而str本身指向的空间没有任何变化,strcpy对空指针解引用导致程序崩溃,如果不是NULL而是其他的值是可以操作的
修改方法:将传入值改成&str,将函数形参修改成**p,或者让函数没有形参,str=GetMenmory
柔性数组:在c99中允许数组的最后一位为未知长度的数组,这个数组的存在条件:
? ? ? ? 1.在结构体中
? ? ? ? 2.最后一个成员
? ? ? ? 3.未知大小的数组
struct good
{
int a;
int a[0】;或int a[];
};
特殊性质:柔性数组前面必须至少有一个其他成员,sizeof返回的结构体大小不包括柔性数组,包涵柔性数组的成员使用malloc进行动态内存分配,分配空间应大于结构的大小,以适应柔性数组的大小,而结构体定义要变成如下:
接上上面的结构体
struct good *ps=(struct good*)malloc(sizeof(struct good)+10*sizeof(int));
ps->a=2;
int i=0;
for(i=0;i<10;i++)
{
ps->arr[i]=i;
}
如果空间不够
struct good*p=realloc(ps,sizeof(struct good)+15*sizeof(int));
if(p!=NULL)
{
ps=p;
}
for(i=10;i<15;i++)
{
ps->arr[i]=i;
}
free(ps);
也可以将结构体中的数组替换为指针,此时可以理解为类似数组指针的指针
使用柔性数组的优点:方便内存释放,有利于访问速度