• malloc与free


    目录

    前提须知:

    malloc:

    大意:

    头文件:

    申请空间:

    判断是否申请成功: 

    使用空间:

     结果:

    整体代码:

     malloc申请的空间怎么回收呢?

    注意事项:

    使用malloc开辟数组:

    一维数组:

    图解:

    二维数组:

    free:



    前提须知:

    为什么要有动态内存分配 ?

    我们已经掌握的内存开辟⽅式有:

    1. int val = 20;//在栈空间上开辟四个字节
    2. char arr[10] = {0};//在栈空间上开辟10个字节的连续空间
    • 上述开辟内存空间的特点——空间申请之后不容易调整,或者说不能够进行调整,且数组在申明的时候,必须指定数组的⻓度,数组空间⼀旦确定了⼤⼩不能调整。
    • 而就算是变长数组也只是说数组的大小可以使用变量来指定,而一旦数组创建好后,依然是不能调整大小
    • 而对于申请的空间大小不能灵活的调整,C语言就给了: 动态内存管理,给程序员权限,自己申请,自己使用,使用完后,自己释放。

    而开辟和释放所需要用到的函数就是malloc与free

    • malloc是用来申请内存的
    • free是用来释放内存的

    malloc:

    C语⾔提供了⼀个动态内存开辟的函数:

     void* malloc (size_t size);
    

    大意:

    想要多少字节就向内存申请多少个字节, 申请成功后会返回一共空间的起始地址,开辟失败会返回空指针(NULL)。

    头文件:

    #include 

    申请空间:

    1. malloc(10 * sizeof(int));
    2. //申请10个整型的空间 - 40个字节

    判断是否申请成功: 

    1. if (p == NULL)
    2. {
    3. perror("malloc");
    4. return 1;
    5. }
    • 冷知识:return 0 ;表示一共主函数的结束,也表示着一个正确的返回值,而在此时的return 1;表示的是一个返回失败的意思,或是说申请空间失败。
    • return 1;也可以用return 2;或者return 3;表示,只要表示return 0;就行。 

    因为申请成功会返回起始地址,而返回的类型是void*所以我们要进行使用的时候需要进行转化,且我们要使用这个空间时得找一个相对因的变量指针进行存放空间起始地址。

    int *p = (int*)malloc(10 * sizeof(int));

    使用空间:

    1. int i = 0;
    2. for (i = 0; i <10; i++)
    3. {
    4. *(p + i) = i;
    5. }
    6. for (i = 0;i < 10; i++)
    7. { printf("%d",p[i]);
    8. return 0;
    9. }
    •  p+i表示地址,*(p+i)表示地址所指向的元素,所以这是给每个不同地址的不同的元素赋值。
    • p[i]相当于*(p+i)

     结果:

    整体代码:

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

     malloc申请的空间怎么回收呢?

    1. free回收
    2. 自己使用free不释放的时候,程序结束后,也会由操作系统回收
    3. malloc是堆区上申请内存

     

    注意事项:

    • 如果开辟成功,则返回⼀个指向开辟好空间的指针。
    • 如果开辟失败,则返回⼀个 NULL 指针,因此malloc的返回值⼀定要做检查。
    • 返回值的类型是 void* ,所以malloc函数并不知道开辟空间的类型,具体在使⽤的时候使⽤者⾃⼰来决定。
    • 尽量使用free函数进行回收函数,如若使用系统回收,若申请的空间过大,或进行多次申请空间,且不使用free进行回收,系统内存空间可能会出现不够
    • 如果参数 size 为0,malloc的⾏为是标准是未定义的,取决于编译器。 

    使用malloc开辟数组:

    一维数组:

    1. int main()
    2. {
    3. int *p = (int *)malloc(sizeof(int)*100);
    4. return 0;
    5. }

     这就是开辟一百个int类型的元素

    1. int main()
    2. {
    3. int** p = (int**)malloc(sizeof(int) * 3);
    4. return 0;
    5. }

    这也是开辟一维数组

    图解:

     

    开辟了三个空间,空间的类型是int**,用来存放int* 类型的元素

    二维数组

    1. int main()
    2. {
    3. int** p = (int**)malloc(sizeof(int) * 3);
    4. for (int i = 0; i < 3; i++)
    5. {
    6. p[i] = (int *)malloc(sizeof(int) *5);
    7. }
    8. return 0;
    9. }

     开辟一个3*5的二维数组。

    free:

    C语⾔提供了另外⼀个函数free,专⻔是⽤来做动态内存的释放和回收的,函数原型如下:

    void free (void* ptr);
    

     free函数  只能  ⽤来释放动态开辟的内存。

    • 如果参数 ptr 指向的空间不是动态开辟的,那free函数的⾏为是未定义的。
    • 如果参数 ptr 是NULL指针,则函数什么事都不做。
    • malloc和free都声明在 stdlib.h 头⽂件中。
    1. int main()
    2. {
    3. int *p = (int*)malloc(10 * sizeof(int));
    4. if (p == NULL)
    5. {
    6. perror("malloc");
    7. return 1;
    8. }
    9. int i = 0;
    10. for (i = 0; i <10; i++)
    11. {
    12. *(p + i) = i;
    13. }
    14. for (i = 0;i < 10; i++)
    15. {
    16. printf("%d",p[i]);
    17. return 0;
    18. }
    19. free(p);//释放
    20. p = NULL;
    21. return 0;
    22. }

    free(p);
    p = NULL;

    • p内存放的是申请的空间的起始位置。
    • 而free只是把p指向的空间回收了。
    • 而对于以上两段代码我们还得让p指针忘记申请空间的空间起始地址,不然p会变成野指针。
  • 相关阅读:
    【戴师兄数分】excel基础操作——函数专题(个人笔记)
    C# , .netWebApi, WPF 用特性实现类似Java 的Ioc 自动装配@Autowired
    MRO工业品怎么做好供应链?数字化供应链管理系统赋能MRO采购构筑企业核心优势
    超声波模块详细介绍(stm32循迹小车中超声波的介绍)
    VSCode:使用CMakeLists.txt构建C++项目
    【Python】正则表达式判断是否存在连续N个字母
    【开源WebGIS】05-Openlayers访问GeoServer发布的WMS数据并添加标注
    webpack原理篇(五十二):webpack-cli源码阅读
    vue3使用element-plus 树组件(el-tree)数据回显
    医院数字化LIS(检验信息系统)源码
  • 原文地址:https://blog.csdn.net/2301_76445610/article/details/133046342