C 语言动态内存管理

	int a = 10;//在栈空间开辟了4个字节
	int arr[10];//在栈空间连续开辟了10个连续的4字节空间

上面的两行代码开辟空间的方式均是开辟了大小固定的空间。

但是我们实际对空间的需求,不仅仅是上诉的情况。而是随着程序运行的时候我们才知道我们需要的空间要多大,
那数组的编译时开辟空间的方式就不能买满足了。
这时候就需要动态开辟内存了。

动态内存函数的介绍:malloc/calloc/realloc/free

malloc/free

c语言提供了一个动态内存开辟的函数:void* malloc(size_t size);
这个函数向内存申请了一块连续可用的空间,并返回指向这块空间的指针。
1)如果开辟成功,则返回一个只想开辟空间的指针。
2)如果开辟失败,则返回一个NULL指针,因此malloc的返回值一定要做检查。
3)返回值的类型是void* ,所以malloc函数并不知道开辟空间的类型,具体在使用的时候需要使用者自己来决定。
4)如果参数size 为0,malloc的行为是标准的未定义的,有编译器决定。
c语言提供了一个跟他匹配只用的函数free,专门是用来做动态内存的释放和回收,函数原型:
void* free(void* ptr);

free函数用来释放动态开辟的内存。
1)如果参数ptr 指向的空间不是动态开辟的,那么free函数的行为是未定义的。
2)如果参数ptr 是NULL 指针,则函数什么事都不做。

举个栗子

int  main() 
{
	int* ptr = NULL;
	ptr = (int*)malloc(sizeof(int)*10);
	if (ptr != NULL) {
		for (int i = 0; i < 10; i++) {
			*(ptr + i) = 0;                   //初始化
			printf("%p \n",(ptr+i));          //地址
			printf("ptr的值:%d \n", *(ptr + i));//值
		}
	}
	printf("     free(ptr);      \n");  
	free(ptr);								//释放空间
	for (int i = 0; i < 10; i++) {
		printf("%p \n", (ptr + i));
		printf("ptr的值:%d \n", *(ptr + i));
	}
	printf("     ptr = NULL;      \n");
	ptr = NULL;								//原指针置空
	for (int i = 0; i < 10; i++) {
		printf("%p \n", (ptr + i));
	//	printf("ptr的值:%d \n", *(ptr + i));
	}
	return 0;
}

我们看一下运行结果: C 语言动态内存管理_第1张图片
free();后的ptr真正存在的意义仅仅是几个连续的地址,且每个地址没有相应的空间。置空后的ptr地址变成了内存里最开始的几个连续地址。

calloc

c语言还提供了一个函数calloc,它也是用来动态内存分配的
函数原型: void* calloc(size_t num,size_t size);
1)函数的功能是为num个大小为size的元素开辟一块空间,并把空间的每一个字节初始化为0。
2)与函数malloc的区别只在于calloc会返回地址前把申请的空间的每个字节都初始化为0;

如果我们对申请的空间自动初始化,我们用calloc就显得非常方便了。
图例: C 语言动态内存管理_第2张图片

realloc

有的时候我们发现我们以前开辟的空间不够,太小了。或者我们我们之前开辟的空间太大了,为了合理的使用内存
我们就需要对内存的大小做一些灵活的调整。那么realloc 函数就可以做到对 开辟内存大小的调整。
函数原型:void* realloc( void* ptr ,size_t size);

1)ptr是要调整的内存地址。
2)size是调整后的大小。
3)返回值为调整后的内存起始位置。
4)这个函数调整原内存空间大小的基础上,还会将原来内存中的数据移动到新的空间里。
5)realloc在调整内存空间的时候存在两种情况:
情况1.原有空间之后有足够大的空间。
情况2.原有空间之后没有足够大的空间。
举个栗子: C 语言动态内存管理_第3张图片
6)开辟成功返回原地址或者新开辟的空间的地址;失败返回NULL,所以我们要在使用动态开辟的内存之前,要先检查一下是否开辟成功,即ptr!=NULL,我们才能使用。
注意:没有释放不再使用的动态开辟的内存空间会导致内存泄漏!
动态开辟空间以后,不用以后一定要释放,并且正确释放!


你可能感兴趣的:(C 语言动态内存管理)