当前位置:   article > 正文

C语言:动态内存管理(malloc,calloc,realloc,free)_malloc失败会返回null吗

malloc失败会返回null吗

目录

前言

malloc函数

free函数

calloc函数

realloc函数


前言

在这一章节将讲解动态内存分配,它可以在程序的堆区创建一块内存,在这块内存中存什么值就是由自己决定的了

开辟的空间有两个特点:

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

2. 数组在声明时必须指定长度,数组的大小一旦确定就不能调整

在使用这些函数之前我们需要包含他们头文件

#include<stdlib.h>

malloc函数

该函数的作用是开辟一块固定大小连续的空间,并返回指向这块空间的指针

所以它的返回值为void*

里面的参数size是一个以字节为单位的数字,函数会开辟所给的大小

如果malloc开辟空间成功,则按上面所说返回一个指向这块空间的指针

如果malloc开辟空间失败,则会返回NULL指针

因此使用它时一定要进行检查返回值

如果传的size为0,则具体怎么处理看编译器

具体使用malloc函数的代码如下:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. int main()
  4. {
  5. int* p = malloc(sizeof(int) * 4);
  6. if (p == NULL)
  7. {
  8. perror("malloc fail");
  9. return 1;
  10. }
  11. for (int i = 0; i < 4; i++)
  12. {
  13. p[i] = i + 1;
  14. }
  15. for (int i = 0; i < 4; i++)
  16. {
  17. printf("%d ", p[i]);
  18. }
  19. return 0;
  20. }

 首先我们定义了一个int* 类型的指针接收malloc的返回值

并且使用了if 语句判断malloc开辟空间是否成功,如果成功则不会进入if 语句进入下面的语句

然后下面的两个for循环就是正常的给空间赋值和打印,最终结果如下:

但是这样做其实还差了点意思,这个程序其实并不完美,存在内存泄漏的问题

假设我们需要一直跑某一个代码,那么我们如果这样一直使用内存不进行释放的话,迟早有一次内存会被吃满,这种现象叫做内存泄漏

所以为了解决这个问题,我们需要使用另一个函数

free函数

 free是专门用来做动态内存的释放和回收的

该函数没有返回值,参数为一个void* 的指针(想了解void*可以看看我前面的博客)

C语言:指针的基础详解-CSDN博客

注:

1. 如果ptr指向的空间不是动态开辟的,则free函数的行为是未定义的(具体处理方式看编译器)

2. 如果ptr是NULL指针,则函数什么事情都不做

所以与上面动态开辟内存的malloc函数结合起来使用,我们在上面写的代码只需要在最后加上一个free函数释放掉这块空间即可

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. int main()
  4. {
  5. int* p = malloc(sizeof(int) * 4);
  6. if (p == NULL)
  7. {
  8. perror("malloc fail");
  9. return 1;
  10. }
  11. for (int i = 0; i < 4; i++)
  12. {
  13. p[i] = i + 1;
  14. }
  15. for (int i = 0; i < 4; i++)
  16. {
  17. printf("%d ", p[i]);
  18. }
  19. free(p);
  20. p = NULL;
  21. return 0;
  22. }

最后free的参数为p表示释放掉p指向的这块动态开辟的空间

并且我们可以在最后将p置为空指针,以防它变成野指针

calloc函数

calloc跟malloc基本差不多

第一个参数num是需要开辟的空间数量

第二个参数size是每个空间的大小

返回值与malloc一样

calloc与malloc的本质区别就是calloc会将开辟的那块空间的每个字节初始化为0

总结:calloc会初始化,malloc不会初始化

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. int main()
  4. {
  5. int* p = calloc(4, sizeof(int));
  6. if (p == NULL)
  7. {
  8. perror("malloc fail");
  9. return 1;
  10. }
  11. for (int i = 0; i < 4; i++)
  12. {
  13. printf("%d ", p[i]);
  14. }
  15. free(p);
  16. p = NULL;
  17. return 0;
  18. }

 前面的代码我们将malloc换成了calloc,并且将初始化的环节删除了,最终输出结果如下:

可以看到我们并没有给它初始化但是打印出来的结果是0

所以这个函数已经将这块空间给初始化为0了

realloc函数

realloc让动态内存管理更加灵活了

有时候我们会发现申请的空间太小了,有时候又觉得申请的空间太大了浪费,为了合理的使用内存

我们可以使用realloc函数进行调整

第一个参数ptr是要调整的内存地址

第二个参数是调整之后的新大小

 函数返回值为调整之后的内存起始位置

realloc调整空间有两种情况

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

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

如果是情况1则会直接在原来的空间后面直接追加空间,最后返回原来的内存地址

如果是情况2则会在堆空间上另外找一个合适并且有足够大小的空间进行开辟,最后返回新的内存地址 

具体代码如下:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. int main()
  4. {
  5. int* p = malloc(sizeof(int) * 4);
  6. if (p == NULL)
  7. {
  8. perror("malloc fail");
  9. return 1;
  10. }
  11. int* ptr = realloc(p, sizeof(int) * 6);
  12. for (int i = 0; i < 6; i++)
  13. {
  14. ptr[i] = i + 1;
  15. }
  16. for (int i = 0; i < 6; i++)
  17. {
  18. printf("%d ", ptr[i]);
  19. }
  20. free(p);
  21. p = NULL;
  22. return 0;
  23. }

第一个malloc开辟了四个int类型的空间,若此时我们发现不够,则以下用了realloc调整空间

下面使用了ptr来接收realloc将p指向的空间变成6个int类型的空间的起始地址

最后我们给ptr赋值并且打印,结果如下:


本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号