当前位置:网站首页>C语言动态内存分配(1)三种函数讲解

C语言动态内存分配(1)三种函数讲解

2022-08-11 05:16:00 云逸943

前言        

        再学习C语言的历程中,大家想必都学过在内存中开辟空间,一般来说,大家常用的就是对变量,对数组进行内存空间的开辟,我们称这种开辟方式为静态内存分配方式,如下:

//创建变量开辟内存
int val = 20;//在栈空间上开辟四个字节

//创建数组开辟内存
char arr[10] = {0};//在栈空间上开辟10个字节的连续空间

上面这种静态开辟空间的方式有两个特点:

        1. 空间开辟大小是固定的。

        2. 数组在申明的时候,必须指定数组的长度,它所需要的内存在编译时分配。

         但是对于空间的需求,不仅仅是上述的情况。有时候我们需要的空间大小在程序运行的时候才能知道, 那数组的编译时开辟空间的方式就不能满足了。而动态内存的分配可以很好的解决这些问题,那么接下来就来了解了解动态内存的分配是怎样创建的吧!


目录

前言        

一.动态内存函数——malloc

1.malloc函数

2.free函数

3.函数实践 

 二.动态内存函数——calloc

1.calloc

2.函数实践

 三.动态内存函数——realloc

1.realloc

2.函数实践



一.动态内存函数——malloc

1.malloc函数

        malloc函数的作用是向内存申请一块连续可用的空间,并返回指向这块空间的指针。

        注:当使用malloc函数时,参数size_t size使用的数据是以字节为单位创建的。

        使用它所需要引用头文件: <stdlib.h>

        如果开辟成功,则返回一个指向开辟好空间的指针。

        如果开辟失败,则返回一个NULL指针,因此malloc的返回值一定要做检查。

        返回值的类型是 void* ,所以malloc函数并不知道开辟空间的类型,在使用时一定要强制转换为所需要的类型。

        需要注意的是:静态开辟的内存方式(创建变量、数组)是系统在栈区执行的,用完程序就会自动释放;而动态的内存开辟方式是在堆区执行的,手动开辟后就需要手动释放掉,而释放堆区内存的函数用到了free函数!

2.free函数

 Deallocates or frees a memory block.:释放或释放内存块。 

使用free函数的注意事项:

如果参数 ptr 指向的空间不是动态开辟的,那free函数的行为是未定义的。

如果参数 ptr 是NULL指针,则函数什么事都不做。

3.函数实践 

#include<stdio.h>
#include<stdlib.h>

int main(){

int* ptr = NULL;

//动态内存开辟  开辟了num个整型空间
 ptr = (int*)malloc(num*sizeof(int));

 if(NULL != ptr)//判断ptr指针是否为空
 {
 int i = 0;
 for(i=0; i<num; i++)
 {
 *(ptr+i) = 0;
     }
 }
 free(ptr);//释放ptr所指向的动态内存
 ptr = NULL;
 return 0;
}

     注1:一旦动态开辟了堆区内存,就要使用free去释放,否则会造成内存泄露.

        内存泄漏(Memory Leak)是指程序中已动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。

     注2:在最后使用free函数释放了堆区开辟的内存后,还得将指针置为空指针,原因:释放空间后,指针p仍可以指向之前开辟的空间,成为了野指针(很危险),所以将指针P置为空,这样P就找不到之前所开辟的空间了 。


 二.动态内存函数——calloc

1.calloc

         Allocates an array in memory with elements initialized to 0:在内存中分配一个数组,其中元素初始化为0。

        calloc的两个参数:size_t num    ,size_t size

        size_t num :要开辟的个数,

        size_t size:开辟的个数的类型大小(字节数

        calloc函数的作用:函数的功能是为 num 个大小为 size 的元素开辟一块空间,并且把空间的每个字节初始化为0。

        calloc与malloc函数的区别在于:calloc会在返回地址之前把申请的空间的每个字节初始化为全0,malloc只会开辟出相应的内存空间而已。

2.函数实践

 

# include<stdio.h>
#include<errno.h>
#include<stdlib.h>

int main() {
	int* se = calloc(10, sizeof(int));//开辟10个整型空间

        //判断se是否为空指针
       if(se!=NULL){
		int i = 0;
		for (i = 0; i < 10; i++) {
			printf("%d ", *(se + i));
		}
	}
	//0 0 0 0 0 0 0 0 0 0  自动初始化为0

	free(se);
	se = NULL;
	return 0;
}


 三.动态内存函数——realloc

1.realloc

        有时会我们发现开始动态申请的空间太小了,有时候我们又会觉得申请的空间过大了,为了合理的分配内存,我们需要会对内存的大小做调整。那 realloc 函数就可以做到对动态开辟内存大小的调整。可以说这个函数是动态内存分配的点睛之笔!

     

        realloc函数的参数1:void*memblock   (是要调整的内存地址)

        realloc函数的参数2: size_t size           (调整之后新大小)

使用realloc的注意事项: 

返回值为调整之后的内存起始位置。
这个函数调整原内存空间大小的基础上,还会将原来内存中的数据移动到 新 的空间。
realloc在调整内存空间的是存在两种情况:
情况1:原有空间之后有足够大的空间;

情况2:原有空间之后没有足够大的空间 

 如下图展示:

         情况1:要扩展内存就直接在原有内存之后直接追加空间,原来空间的数据不发生变化,函数返回调整之后的空间的起始位置地址。

         情况2 :原有空间之后没有足够多的空间时,则realloc就会重新找一个新的内存区域,将元数据拷贝过去再追加,最后返回新空间的起始位置地址。

 

2.函数实践

# include<stdio.h>
#include<errno.h>
#include<stdlib.h>

int main() {
	int* p = (int*)malloc(40);//开辟10个整型空间
	if (p == NULL) {
		printf("%s\n", strerror(errno));
		return -1;
	}

		int i = 0;
		for (i = 0; i < 10; i++) {
			*(p + i) = i + 1;
			printf("%d ", *(p + i));
		}
		printf("\n");

		//扩容——realloc
		//为指针p指向的内存空间再扩容40字节(共80字节),存放到新指针中
		int* ptr = (int*)realloc(p, 80);
		//若是此内存后有足够空间开辟,就延续之前的地址空间,		
							//若是没有足够空间,系统会找一块足以能放下要求的空间,

			for (i = 0; i < 10; i++) {
				printf("%d ", *(ptr + i));
			}
		free(ptr);
		ptr = NULL;
	return 0;
}

        注:当扩大或者缩小内存容量后,会使用新指针ptr接收调整之后的内存,而旧的指针p则不用管,系统会自动释放掉p,不需要为p再使用free函数了 。


        以上就是我对动态内存分配知识点的讲解了,之后我还会出一篇我们在学习动态内存分配时常见的一些动态内存错误案例讲解,下期再见!记得一键三连哟~

原网站

版权声明
本文为[云逸943]所创,转载请带上原文链接,感谢
https://blog.csdn.net/weixin_69283129/article/details/126101664