使用时应加上头文件 #include
一.申请动态内存
申请动态内存:malloc/calloc/realloc,申请的动态内存分为多少份此函数无法明确,所以应在malloc/calloc/realloc前面加上类型
1.malloc
malloc函数的形参为所要申请的动态内存字节数(动态数组总共所占字节数),若申请成功,此函数会将申请的动态连续内存(动态数组)的首地址返回,申请失败返回空指针。
例如:int *p1=(int *)malloc(20); //申请20个字节的内存,类型为int 每个int所占字节数为4,所以此数组可放5个int变量
free(p1); //释放掉这20个字节的内存
int *p2=(double *)malloc(32); //申请32个字节的内存,类型为double 每个double所占字节数为8,所以此数组可放5个double变量
free(p2);
int *p3=(char *)malloc(10); //申请10个字节的内存,类型为char 每个char所占字节数为1,所以此数组可放10个char变量
free(p3);
动态内存在堆里,它突破了局部变量的作用域和生存期,如果申请动态内存成功,只有free函数或程序运行结束,否则此段内存始终可以使用,它突破局部变量的作用域和生存期。
例:
#include
#include
int *show1()
{
int arr1[]={0,1,2,3,4};
return arr1;
}
int *show2()
{
int *arr2=(int *)malloc(5*sizeof(int));
for(int i=0;i<5;i++)
{
arr2[i]=i;
}
return arr2;
}
int main()
{
int *p1=show1();
int i;
for(i=0;i<5;i++)
{
printf("p1[%d]=%d ",i,p1[i]);
}
printf("\n\n\n\n\n");
int *p2=show2();
for(i=0;i<5;i++)
{
printf("p2[%d]=%d ",i,p2[i]);
}
free(p2);
return 0;
}
结果:
2.calloc
calloc(数组长度,数组每一个单元格所占字节数)
calloc与malloc区别:申请的动态数组会初始化为0;
例:
#include
#include
int main()
{
int *arr1= (int *)malloc(10*sizeof(int));
int i;
for(i=0;i<10;i++)
{
arr1[i] = 0;
}
for(i=0;i<10;i++)
{
printf("arr1[%d]=%d ",i,arr1[i]);
}
printf("\n\n\n\n");
//等同以下操作
int *arr2 = (int *)calloc(10,sizeof(int));//10为数组长度,每一个单元格占4字节
for(i=0;i<10;i++)
{
printf("arr2[%d]=%d ",i,arr2[i]);
}
free(arr1);
free(arr2);
return 0;
}
结果:
3.realloc
修改动态数组的大小。
当扩大动态数组的大小时,会重新申请一块内存(此时所需要的内存总字节数),再将旧内存中的内容复制到新的内存中,释放掉旧内存,将新内存的首地址赋给保存旧内存首地址的指针,将申请新内存时保存新首地址的指针置空。
当缩小动态内存的大小时,无操作。
realloc(旧内存的首地址,此时所需要的内存总字节数);
例:
1.扩大动态内存:
#include
#include
int main()
{
int *p1 = (int *)malloc(10*sizeof(int));//先申请10个长度(共40字节)整型动态数组
int i;
for(i=0;i<10;i++)
{
p1[i] = 10*i;
}
p1 = (int *)realloc(p1,20*sizeof(int));//将动态数组的长度修改为20(共80字节)
for(i=0;i<10;i++)
{
printf("p1[%d]=%d ",i,p1[i]);
}
free(p1);
printf("\n\n\n\n\n");
//下面的代码等同realloc
int *p2 = (int *)malloc(10*sizeof(int));
for(i=0;i<10;i++)
{
p2[i] = 10*i;
}
int *q = (int *)malloc(20*sizeof(int));
for(i=0;i<10;i++)
{
q[i] = p2[i];
}
p2 = q;
q = NULL;
for(i=0;i<10;i++)
{
printf("p2[%d]=%d ",i,p2[i]);
}
free(p2);
return 0;
}
结果:
2.缩小动态内存
#include
#include
int main()
{
int *p = (int *)malloc(10*sizeof(int));
int i;
for(i=0;i<10;i++)
{
p[i] = 10*i;
}
printf("缩小内存前%d\n",p);
for(i=0;i<10;i++)
{
printf("p[%d]=%d ",i,p[i]);
}
printf("\n\n\n\n\n");
p = (int *)realloc(p,5*sizeof(int));
printf("缩小内存后%d\n",p);
for(i=0;i<10;i++)
{
printf("p[%d]=%d ",i,p[i]);
}
free(p);
printf("\n释放动态内存后%d\n",p);
return 0;
}
结果:
二.释放动态内存
释放动态内存:free
free(动态内存首地址)
使用完动态内存后要用free释放掉申请的动态内存,否则会造成内存泄漏(可使用的内存越来越少),释放掉动态内存后要将保存原动态内存首地址的指针置空,此时此段内存已被操作系统回收,这个指针为野指针。
free崩溃的原因:
1.越界
例:
int main()
{
int *p = (int *)malloc(10*sizeof(int));
for(int i=0;i<=10;i++) //应为i<10
{
p[i] = 0;
}
free(p);
return 0;
}
2.修改指针指向
例;
int main()
{
int *p = (int *)malloc(10*sizeof(int));
for(int i=0;i<10;i++)
{
*p = 0;
p++; //p的指向改变
}
free(p);
return 0;
}
3.重复释放同一段内存
例;
int main()
{
int *p = (int *)malloc(10*sizeof(int));
for(int i=0;i<10;i++)
{
p[i] = i;
}
int *q = (int *)malloc(20*sizeof(int));
for(int i=0;i<10;i++)
{
q[i] = p[i];
}
free(p);
p = q;
free(p);
free(q);// 应将q = NULL;
return 0;
}
4.释放非动态内存
例:
int main()
{
int arr[10];
free(arr);
return 0;
}