动态内存创建与释放

使用时应加上头文件 #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;
}

结果:

动态内存创建与释放_第1张图片

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张图片

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;
}

结果:

动态内存创建与释放_第3张图片

二.释放动态内存

释放动态内存: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;
}

你可能感兴趣的:(C)