• 动态内存分配【C语言】


    在这里插入图片描述


    🚠malloc函数和free函数

    🚜malloc函数介绍

    👉malloc函数传送门

    malloc函数是C语言提供给我们的一个动态内存开辟的函数,他的使用形式为:

    void* malloc (size_t size);

    我们传递给malloc函数一个无符号整型,malloc函数申请一段size大小的内存块,如果申请成功就返回一个指向该内存起始位置的指针,该指针为void*类型。如果申请失败,则返回一个NULL指针。

    💙free函数介绍

    👉free函数传送门

    free函数和3个动态内存分配函数(malloccallocrealloc)总是成对出现的,在需要时进行动态内存分配,在不需要时将动态分配的内存进行释放归还给系统,有借有还,再借不难。如果我们只进行内存申请而不归还,那么系统的内存就会被我们一点一点的吃掉,当一个工程足够大的时候,不进行内存释放可能会造成程序崩溃,带来严重的后果。因此我们应该注意动态申请到的内存在不需要的时候我们要及时释放。

    void free (void* ptr);

    在释放内存时,我们只需要将指向动态内存申请的空间的指针传递给free函数即可。

    🚕malloc函数使用

    malloc函数的使用介绍我们通过下面的代码来进行介绍,如下代码:

    #include 
    #include 
    
    int main()
    {
    	int* p = NULL;
    	//动态内存申请
    	p = (int*)malloc(10 * sizeof(int));
    
    	if (p == NULL)
    	{
    		printf("申请失败!\n");
    		exit(-1);
    	}
    	int i = 0;
    	for (i = 0; i < 10; i++)
    	{
    		*(p + i) = i;
    	}
    	for (i = 0; i < 10; i++)
    	{
    		printf("%d ", *(p + i));
    	}
    	//内存释放
    	free(p);
    	p = NULL;
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    在代码的开始,我们定义了一个int*类型的指针,并将其赋值为空,然后通过malloc函数申请40个字节的空间。(sizeof(int)计算int类型的大小)因为malloc函数返回的是void*类型的指针,因此我们需要将其进行强制类型转换为int*类型。

    在动态内存申请之后,我们一般都会进行判断,看看是不是申请成功,如果p指针指向NULL的话,就表示动态内存申请失败,打印错误信息,结束程序。如果成功则继续接下来的操作。

    代码中我们是对申请到的40个字节进行赋值,然后打印,打印完后对内存进行释放,把p指针传给free函数,释放完内存后将指针p置空。打印结果如下图所示:

    在这里插入图片描述

    ❤️calloc函数

    💛calloc函数介绍

    👉calloc函数传送门

    calloc函数是申请num个大小为size的空间并将其赋值为0,申请到的空间总大小为num*size个字节,使用格式为:

    void* calloc (size_t num, size_t size);

    calloc函数与malloc函数类似,如果calloc函数申请内存成功,返回指向该地址起始位置的指针,申请失败的话则返回NULL,返回指针类型为void*

    💓calloc函数使用

    calloc函数的使用我们通过以下代码来进行介绍,如下代码:

    #include 
    #include 
    
    int main()
    {
    	int* p = NULL;
    	//动态内存申请
    	p = (int*)calloc(10, sizeof(int));
    
    	if (p == NULL)
    	{
    		printf("申请失败!\n");
    		exit(-1);
    	}
    	int i = 0;
    	for (i = 0; i < 10; i++)
    	{
    		*(p + i) = i; 
    	}
    	for (i = 0; i < 10; i++)
    	{
    		printf("%d ", *(p + i));
    	}
    	//内存释放
    	free(p);
    	p = NULL;
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    我们还是定义一个int*类型的指针p,然后用calloc函数申请一段num为10,size为4的总大小为40个字节的空间,紧接着对指针p进行判断,为空的话内存申请失败,结束程序。不为空则继续接下来的操作。

    代码中我们还是进行赋值操作,然后打印,在打印完之后对内存进行释放,然后将指针p置为空。我们运行来观察结果,如下图:

    在这里插入图片描述
    我们还可以调试来观察calloc函数的赋值操作,如下图所示:

    calloc

    可以看到用calloc函数申请的内存里面全都被置为了0,而我们用malloc函数申请的内存则为不确定的数,如下图所示:

    在这里插入图片描述
    总的来说,malloc函数和calloc函数还是非常相似的,区别在于malloc函数的参数只有一个,并且申请的内存不进行初始化,而calloc函数的参数有两个,申请到的空间会进行初始化赋值为0。

    💜realloc函数

    💚realloc函数介绍

    👉realloc函数传送门

    realloc函数的出现让我们的动态内存管理变得更加灵活,因为有时候我们会觉得在malloc或者calloc函数上申请的空间太大了或者太小了,当我们要对内存的大小进行灵活的处理时,realloc函数就可以对动态内存申请的空间进行调整。函数的原型如下:

    void* realloc (void* ptr, size_t size);

    realloc函数有两个参数,第一个为指向需要扩容空间的起始位置的指针ptr,第二个为调整后的字节大小size,如果申请成功,返回指向该空间起始位置的指针,类型为void*,如果失败则返回空指针。

    🌟realloc函数特殊说明

    realloc函数进行扩容有两种情况,一种是当原空间的后面拥有足够的空间的时候,扩容时就在该空间的后面进行扩容,如下图所示:

    在这里插入图片描述
    第二种情况为当原空间的后面空间不足以进行扩容操作时,就会在新的空间进行扩容,扩容的大小为原空间和扩容空间之和,并且会将原空间的数据拷贝到扩容后的空间上,然后原空间会主动进行释放,如下图所示:

    在这里插入图片描述

    realloc函数的第一个参数可以为NULL,此时的realloc函数功能相当于malloc函数。

    💘realloc函数使用

    realloc函数使用的介绍我们用一段代码来分析,如下代码:

    #include 
    #include 
    
    int main()
    {
    	int* p = NULL;
    	//动态内存申请
    	p = (int*)malloc(10 * sizeof(int));
    
    	if (p == NULL)
    	{
    		printf("申请失败!\n");
    		exit(-1);
    	}
    	int i = 0;
    	for (i = 0; i < 10; i++)
    	{
    		*(p + i) = i;
    	}
    
    	// 扩容
    	int* ptr = (int*)realloc(p, 20 * sizeof(int));
    	if (ptr == NULL)
    	{
    		printf("realloc!\n");
    		exit(-1);
    	}
    	p = ptr;
    
    	for (i = 10; i < 20; i++)
    	{
    		*(p + i) = i;
    	}
    
    	for (i = 0; i < 20; i++)
    	{
    		printf("%d ", *(p + i));
    	}
    	//内存释放
    	free(p);
    	p = NULL;
    	ptr = NULL;
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    我们用malloc函数进行动态内存申请40个字节,申请成功后给空间进行赋值,后面我们又使用realloc函数进行扩容,扩容到原来的两倍80个字节,接下来给扩容到的空间继续赋值,然后进行打印,打印完成之后对空间进行释放,然后将指针p和指针ptr置为NULL。运行代码我们来观察结果,如下图所示:

    在这里插入图片描述

    💥总结

    动态内存申请的空间都要记得释放,malloc函数,calloc函数和realloc函数总是成对出现的,realloc函数可以扩容也可以缩小空间,在缩小空间时我们要注意内存的大小要足以放下我们原有的数据。合理运用动态内存申请函数可以帮助我们在管理空间大小上事半功倍,如果觉得文章有帮助的话就给个一键三连吧!有疑问也可以在评论区留言哦!在这里插入图片描述

    在这里插入图片描述

  • 相关阅读:
    Linux驱动之INPUT设备驱动
    3. 【containerd】image 什么时候会被垃圾回收
    YOLOv8血细胞检测(4):Dual-ViT:一种多尺度双视觉Transformer ,Dualattention助力小目标检测| 顶刊TPAMI 2023
    思腾云计算
    万集wlr718雷达测试记录和stm32h745驱动编写,数据分析
    一文让你理解Linux权限问题
    图像处理 OpenCV简介
    Nginx:配置
    雨量水位监测显示屏内涝状况提前掌握
    值传递还是引用传递(By Value or By Reference)
  • 原文地址:https://blog.csdn.net/wzh18907434168/article/details/127343541