---------------start reading---------------
前言
当主函数传参到功能函数,传参的值不确定但我们又想给一个相应大小的数组变量时,我们就会用到动态内存,动态内存就是程序员自己开辟的一块内存空间
动态内存的特点
- 能给出不确定的变量内存
- 给的内存很大
- 动态内存在“堆”里取内存
- 需要使用<stdlib.h>头文件
今天要给大家说的是四个动态内存函数的用法
malloc
calloc
realloc
free
1、malloc
malloc:在堆中分配自定义大小的内存
malloc函数的用法:
(int)malloc(n*sizeof(int))
- malloc函数的返回值是void,所以malloc前要加上强转的数据类型如:int *p=(int )malloc(nsizeof(int))。
- malloc的参数只有一个,为开辟的字节长度。n*sizeof(int),n表示想给的数组的长度,sizeof(int)表示一个整形数据的大小。
int *Fun(int n)
{
int *p = (int *)malloc(n*sizeof(int)); //malloc(字节)
for(int i=0;i<n;i++)
{
p[i] = 0;
}
return p;
}
这里使用malloc就表示,定义一个整形的指针变量,他的大小为n*sizeof(int),用数组来解释就是定义了一个长度为n的整形数组。
2、calloc
创建10n长度的整型数组,且每个格子值置0并返回
int* Fun(int n)
{
int * p = (int * )malloc(n*sizeof(int));
for(int i=0;i<n;i++)
{
p[i] = 0;
}
return p;
}
calloc:分配动态内存并将每一个值初始化为0.
calloc和malloc相比只多了一个初始化为0的功能,开辟内存的功能是一样的。所以calloc不常用,因为不是每一个数据都需要置零。
3、free
malloc开辟的内存空间很大,如果多使用两个系统内存岂不是都被占用了。开辟内存没有释放,就会导致拖慢程序,我们称之为“内存泄漏”。这时候就要用到free函数。
free:释放申请的内存。
int * p = (int * )malloc(n*sizeof(int));
free(p);
4、realloc
如何将动态内存扩容
int main()
{
int n = 10;
int *p = (int *)malloc(n*sizeof(int));
int i;
for(i=0;i<n;i++) //模拟数组被使用
{
p[i] = i; //旧房子
}
//realloc,扩容
int *q = (int *)malloc(n*2*sizeof(int));//1、买新房
for(i=0;i<n;i++)//2、搬家
{
q[i] = p[i];
}
free(p);//3、卖旧房
p = q; //4、更新地址
q = NULL;
printf("%d\n",p);
return 0;
}
我们把扩容类比成搬进大房子,步骤如下:
- 买个新房子(新定义一个内存更大的指针)
- 将旧房子里的家具放到新房子里(将旧指针的值赋值给新指针)
- 卖掉旧房子(将旧指针的空间释放,但仍然保留地址)
- 更新地址,告诉别人新加的地址(将新地址附给旧地址)
realloc:用来修改动态内存的大小,主要是扩容,一般缩小内存,就算是缩小了,实际上编译器也不会将这个变量的动态内存变小,这只是字面上的假象。
p=(int )realloc(p,2n*sizeof(int)),将原数组扩大两倍的内存
附加的话 :free,容易引起程序崩溃
free,能帮我们解决内存泄露的问题,但是使用free一定要小心啊!free有头信息,有尾信息,破坏了其中一个都会引起程序崩溃,现在就让我们来看看free高频引起程序崩溃的原因。
-
数组越界破坏尾信息(地址修改),程序奔溃。(开辟内存少了,malloc,realloc可能会忘了乘sizeof()导致开辟内存空间小了)
-
移动了指针的位置,找不到头信息。移动了指针的位置,找不到头信息。
{
*p==0;
p++;
} -
重复释放同一内存
*p2=p2;
free(p2),free(p1) -
释放不是动态内存创建的变量
int a;
free(a)
以上都会引起程序崩溃
--------------end---------------