在写代码的时候我们常常遇到这样的问题,在开始定义了内存空间来存储所使用的数,比如 int arr[5] ,有时写到最后我们所定义的内存空间不够用,超出所定义的内存大小,或者我们所定义的内存空间太大了,占用太多的空间,那么有没有一种方法能使我们所定义的空间内存刚刚用户完,即不超出,也不浪费。
1. malloc()函数和free()函数
我们在开辟内存空间时,使用动态内存来开辟,要在头文件中加入stdlib.h文件(内存区域在堆里面)
int *p=(int *)malloc(n * sizeof(int))//相当于int p[n]
在这个程序中,首先开辟了n个int类型的空间,然后把p指向这个空间的位置。在这里的指针是指向第一个int值。并不是我们全部开辟的n个int的空间。这就和数组一样,指向数组的指针式指向数组首元素的地址,并不是整个数组的元素。所以,在这里我们的操作也和数组是一样的,p[0]就是第一个元素,p[1]就是第二个元素。
eg:找出1~20之间的所有素数并且输出
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <malloc.h>
void SiftPrime(int n)
{
int *p = (int *)malloc(n*sizeof(int));//等同int p[n];
assert(p != NULL);//加断言,判断p不能为空
if(p == NULL)
{
return ;
}
int i;
for(i=0;i<n;i++)
{
p[i] = 1;
}
p[0] = p[1] = 0;
for(i=2;i<n;i++)
{
for(int j=i+1;j<n;j++)
{
if(j%i == 0)
{
p[j] = 0;
}
}
}
for(i=0;i<n;i++)
{
if(p[i] != 0)
{
printf("%d\n",i);
}
}
}
int main()
{
SiftPrime(20);
return 0;
}
当我们使用malloc()开辟完内存空间以后,我们所要考虑的就是释放内存空间,在这里,C给我们提供了free()函数。free()的参数就是malloc()函数所返回的地址,释放先前malloc()函数所开辟的空间。 对于上面我们所开辟的空间进行释放,那么我们就可在最后加上一句 free(p),释放 申请的动态内存,如果不释放,将会造成内存泄露。
2.free()的重要性
free()函数在动态内存中使用比较多,但是在使用的时候经常会出现崩溃问题,主要的崩溃方面有以下:
1.越界,漏泄sizeof,realioc(下面会讲到这个函数)第二个参数写错
int main()//free崩溃情景1
{
int *p = (int *)malloc(10*sizeof(int));
for(int i=0;i<=10;i++)//越界
{
p[i] = 0;
}
free(p);
return 0;
}
2. 修改了指针的指向
int main()//free崩溃情景2
{
int *p = (int *)malloc(10*sizeof(int));
for(int i=0;i<10;i++)
{
*p = 0;
p++;//修改了指针的指向
}
free(p);
return 0;
}
3. 重复释放同一段内存
int main()//free崩溃情景3
{
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);重复释放
return 0;
}
4.释放非动态内存 int main()//情景4
{
int arr[10];//非动态内存
free(arr);
return 0;
}
3.calloc()函数和realloc()函数
在了解calloc之前,我想先写一道题,申请一段10个大小的动态内存,并且让10个数输出,都赋值为0
int main()
{
int *arr = (int *)malloc(10*sizeof(int));
for(int i=0;i<10;i++)
{
arr[i] = 0;
printf("%d ",arr[i]);
}
return 0;
}
那么为了方便一句话写出,那么就可以使用calloc()函数来写
int main()
{
int *arr = (int *)calloc(10,sizeof(int));//0,0,0,00,
for(int i=0;i<10;i++)
printf("%d ",*arr);
return 0;
}
通过上面的例子,我们可以知道calloc()函数有两个参数,并且这两个函数都是size_t类型(unsigned int类型)的数。第一个参数在这里所说的是所需要开辟的内存单元数量,第二个参数是每个单元的字节的大小。
realloc()函数用来修改一个原先已经分配的内存的大小。使用这个函数,你可以让一块内存增大还是缩小。当扩大时,这块内存原先的内容会依然保留,新增加的添加到原先的后面。缩小时,该内存的尾部部分内存去掉,剩余保留。
注意:对于realloc()函数,如果原先的内存无法修改,这时候realloc()函数再会分配一块内存,并且把原先那块内存的内容复制到上面去。所以,使用了realloc函数以后,你这时候在使用的就该是realloc函数返回的新指针了。当realloc函数的第一个参数是NULL时,这时候我们可以把它当作是malloc()函数。
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *p = (int *)malloc(10*sizeof(int));
int i;//模拟p被使用
for(i=0;i<10;i++)
{
p[i] = 10*i;
}
printf("%d\n",p);
p = (int *)realloc(p,10*sizeof(int));
printf("%d\n",p);
free(p);
printf("%d\n",p);//释放后不为空
/*//下面的代码等同realloc
int *q = (int *)malloc(20*sizeof(int));//在原来的基础上再开辟10个空间
for(i=0;i<10;i++)
{
q[i] = p[i];
}
p = q;
q = NULL;*/
return 0;
}
才开始学C,有写的不对的地方,希望各位大神能多指导指导。