C语言动态内存分配与释放

内存静态存储区(static):全局变量、静态变量(static int a;)

内存动态存储区(栈stack):局部变量

内存自由存储区(堆heap):临时用数据

其中静态存储区、动态存储区的变量空间开辟和释放自动进行,不需要程序人员操作内存;

只有堆区需要手动开辟和释放空间:静态开辟——在编译时刻,数组的空间大小就开辟完成;

动态开辟——malloc、calloc、realloc;手动释放空间free


void *malloc(unsigned int size);   开辟size大小数目的字节空间

void *calloc(unsigned n,unsigned size);   开辟n个字节块大小为size的内存空间

void *realloc(void *p,unsigned int size);   第一次p指针开辟长度不够,重新选址开辟size大小数目的字节空间


malloc

#include
#include
int main()
{
	int n;
	printf("input n:>");
	scanf("%d",&n);
	int *p=(int *)malloc(sizeof(int)*n);   //申请开辟空间
	if(NULL==p)
	{
		printf("malloc memory fail!\n");
		exit(1);   //检查malloc开辟空间是否成功,失败p无指向退出程序
	}
	for(int i=0;i
C语言动态内存分配与释放_第1张图片

C语言动态内存分配与释放_第2张图片


calloc

#include
#include

int main()
{
	int n;
	printf("input n:>");
	scanf("%d",&n);
	int *p=(int *)calloc(n,sizeof(int));   //申请开辟n块大小为sizeof(int)个字节的空间
	if(NULL==p)
	{
		printf("malloc memory fail!\n");
		exit(1);   //检查malloc开辟空间是否成功,失败p无指向退出程序
	}
	for(int i=0;i

realloc

#include
#include
void main()
{
	int *p=(int *)malloc(sizeof(int)*5);
	if(NULL==p)
	{
		printf("malloc memory fail!\n");
		exit(1);
	}
	for(int i=0;i<5;++i)
	{
		p[i]=i+1;
	}
	//起初申请的5个空间不够用
	p=(int *)realloc(p,sizeof(int)*10);   
	//realloc对p所指的原始空间进行开辟,但开辟空间前后p所指的内存地址不一定一样
	//把原来的5个扩展为10个,用原来的指针p接收realloc的返回值,如果没有接收指针p,会丢失先前空间的值
	if(NULL==p)
	{
		printf("malloc memory fail!\n");
		exit(1);
	}
	for(i=5;i<10;++i)   
	{
		p[i]=i+1;
	}
	for(i=0;i<10;++i)
	{
		printf("%d",p[i]);
	}
	system("PAUSE");
}

realloc对p所指的原始空间进行开辟,但开辟空间前后p所指的内存地址不一定一样
把原来的5个扩展为10个,用原来的指针p接收realloc的返回值,如果没有接收指针p,会丢失先前空间的值
第一次申请空间在内存里有个位置,第二次申请空间时,会检查内存里其后的空间大小是否满足申请大小:
如果满足,可以不修改第一次p的指向,连续地在其后开辟空间
如果不满足,要在内存中寻找满足大小的空间,如果找不到就开辟失败NULL,找到了就返回该空间的地址,并存放值

C语言动态内存分配与释放_第3张图片
C语言动态内存分配与释放_第4张图片


自定义函数模拟分析realloc过程,还原第一次被开辟空间被free释放过程

#include
#include
#include
//模拟realloc开辟空间过程自定义函数my_realloc,第一次被开辟空间free释放
void* my_realloc(void *p,size_t size)   //size_t的类型在底层是无符号整型
{
	void *new_p=malloc(size);
	if(NULL==new_p)
	{
		printf("malloc memory fail!\n");
		exit(1);
	}
	memcpy(new_p,p,size);   //内存拷贝函数,将p指针空间的size个元素拷贝给new_p指针空间
	free(p);   //释放第一次开辟的空间
	p=new_p;   //把新开辟空间地址赋值给第一次开辟空间定义的指针变量p
	return p;
}
void main()
{
	int *p=(int *)malloc(sizeof(int)*5);
	if(NULL==p)
	{
		printf("malloc memory fail!\n");
		exit(1);
	}
	for(int i=0;i<5;++i)
	{
		p[i]=i+1;
	}
	//起初申请的5个空间不够用,自定义my_realloc重新拷贝函数
	p=(int *)my_realloc(p,sizeof(int)*10);
	if(NULL==p)
	{
		printf("malloc memory fail!\n");
		exit(1);
	}
	for(i=5;i<10;++i)   
	{
		p[i]=i+1;
	}
	for(i=0;i<10;++i)
	{
		printf("%d",p[i]);
	}
	system("PAUSE");
}
C语言动态内存分配与释放_第5张图片


void类型指针是“指向空类型”或“不指向确定的类型”的数据

注意melloc、alloc、realloc函数原本返回值类型就是void型指针,所以要想给真实类型指针赋值,需要进行强制类型转换

#include
#include
void main()
{
	int a=10;
	double d=12.34;
	int *p=(int *)&d;   //强制指针类型转换才能进行赋值

	void *pv=&a;   //void泛型指针
	pv=&d;   //void型指针可以接收一切类型地址
	//但由于其类型未知无法为其开辟空间,不能进行pv++操作
	int *pa=(int *)pv;   //也不能用void型指针给确定类型指针赋值
	//void类型不能转换成真实类型,需要强制类型转换才能赋值
}





你可能感兴趣的:(C++)