动态内存管理那些事:malloc、calloc、realloc、free 上

简介: 动态内存管理那些事:malloc、calloc、realloc、free

文章目录

一、为什么存在动态内存分配

🎗 在之前我们都是这样开辟空间的:

int i = 20; //在栈空间开辟4个字节

char arr[10] = { 0 }; //在栈空间开辟10个字节的连续空间

特点

1️⃣ 开辟的空间大小是固定的

2️⃣ 数组在声明的时候,必需包含常量值 (指定数组长度)

小结

以往开辟空间的方式不够灵活,有很大的局限性 (有时候我们需要的空间大小在程序运行的时候才能知道)

所以这篇文章主要了解在内存堆上开辟空间所使用的函数

二、动态内存函数的介绍

💦 malloc

⭕ 函数信息

#include<stdio.h>
#include<stdlib.h>
int main()
{
  //假设开辟10个整型的空间:
  int arr[10];//1.栈区开辟
  int* p = (int*)void* p = malloc(10 * sizeof(int));//2.堆区开辟
  /*-----------------分割线-----------------*/
  //使用
  //1.开辟失败
  if(p == NULL)
  {
    perror("main");
    return 0;
  }
  //2.开辟成功
  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️⃣ malloc向内存申请一块连续可用的空间,且开辟成功时返回指向那块空间的地址;开辟失败返回NULL

2️⃣ 因为malloc函数的返回值是void*类型,所以在使用某一类型的指针变量接收时,也要强制类型转换为对应的类型

3️⃣ 如果malloc开辟失败,可能会对空指针进行非法解引用操作,所以malloc开辟的空间一定要检查

4️⃣ 使用完malloc开辟的空间,要主动回收空间。因为在回收空间后,那块空间的使用权已经不是自己能控制了,且能通过指针再去寻找到那块空间,所以为了避免非法访问,通常会主动将指向那块空间的指针置为NULL

💦 free

⭕ 函数信息

#include<stdio.h>
int main()
{
  int a = 10;
  int* p = &a;
  free(p);//1.err,回收栈空间
  p = NULL;
  free(NULL)//2.等同于-> //free(NULL)
  return 0;
}

小结

1️⃣ 如果参数ptr指向的空间不是动态开辟的,那么free函数的行为是标准未定义的

2️⃣ 如果参数ptr是NULL指针,则视为无效代码

3️⃣ 关于回收空间有2种方式:一是main函数结束后,开辟的空间会被动的还给OS,但是对于一个每天24小时不停跑的程序来说,如果不主动回收不用的空间的话,剩余的空间将会越来越少。二就是主动的把不用的空间主动回收掉

💦 calloc

⭕ 函数信息

#include<stdio.h>
#include<stdlib.h>
int main()
{
  //malloc和calloc都未主动初始化
  //1.malloc
  int* p = (int*)malloc(40);
  if(p == NULL)
    return 1;
  int i = 0;
  for(i = 0; i < 10; i++)
  {
    printf("%d\n", *(p + i));
  }
  free(p);
  p = NULL;
  //2.calloc
  int* q = (int*)calloc(10, sizeof(int));
  if(q == NULL)
    return 1;
  for(i = 0; i < 10; i++)
  {
    printf("%d\n", *(q + i));
  }
  free(q);
  q = NULL;
  return 0;
}

💨 结果:

小结

1️⃣ calloc相比malloc来说:calloc会主动初始化开辟的内存空间

💦 realloc

🎗 realloc的出现让动态内存管理更加灵活

在申请空间的时候,有时我们会发现过大了或过小了,需要灵活的调整:而能实现灵活调整的函数其实是realloc,所以malloc、calloc、realloc中realloc是毫无争议的一把手

⭕ 函数信息

#include<stdio.h>
#include<stdlib.h>
int main()
{
  //1.使用calloc开辟10个整形大小
  int* p = (int*)calloc(10, sizeof(int));
  if(p == NULL)
  {
    perror("main");
    return 0;
  }
  //2.使用开辟的空间
  int i = 0;
  for(i = 0; i < 10; i++)
  {
    *(p + i) = 5;
  }
  //3.到了这里还需要10个整型空间,而p所指向的空间已经被使用完了,所以使用realloc调整空间  
  //为什么这样设计,请看正面详解:
  int* pnew = (int*)realloc(p, 20 * sizeof(int));
  if(pnew != NULL)
  {
    p = pnew; 
  }
  //.回收空间
  free(p);
  p = NULL;
  return 0;
}

📝详解:

🎗 realloc开辟原理

❓❔ 思考:如何合适的接收realloc的地址呢

✖ int* p = (int*)realloc(p, 20 * sizeof(int));

如果用旧地址去接收:realloc有可能找不到合适的空间,来调整大小,这时就返回NULL。此时再交给p,不仅空间没开辟好,旧空间的内容也找不到了

—— 偷鸡不成蚀把米


✔ int* pnew = (int*)realloc(p, 20 * sizeof(int));

先用新地址接收,如果开辟成功再把它赋值给旧空间,这样不仅避免了旧空间的丢失,同样也适用场景一、场景二

🎗 realloc单独使用时能实现malloc的效果 (不会初始化)

#include<stdio.h>
#include<stdlib.h>
int main()
{
  int* p = (int*)realloc(NULL, 40);//同int* p = (int*)malloc(40);
  if (p == NULL)
    return 1;
  int i = 0;
  for (i = 0; i < 10; i++)
  {
    printf("%d\n", *(p + i));
  }
  free(p);
  p = NULL;
  return 0;
}

💨 结果:


相关文章
|
4月前
|
安全 C语言 C++
比较C++的内存分配与管理方式new/delete与C语言中的malloc/realloc/calloc/free。
在实用性方面,C++的内存管理方式提供了面向对象的特性,它是处理构造和析构、需要类型安全和异常处理的首选方案。而C语言的内存管理函数适用于简单的内存分配,例如分配原始内存块或复杂性较低的数据结构,没有构造和析构的要求。当从C迁移到C++,或在C++中使用C代码时,了解两种内存管理方式的差异非常重要。
172 26
|
程序员 C++ 容器
在 C++中,realloc 函数返回 NULL 时,需要手动释放原来的内存吗?
在 C++ 中,当 realloc 函数返回 NULL 时,表示内存重新分配失败,但原内存块仍然有效,因此需要手动释放原来的内存,以避免内存泄漏。
一刻也没有为它哀悼~接下来登场的是动态内存分配的malloc与realloc以及free函数
一刻也没有为它哀悼~接下来登场的是动态内存分配的malloc与realloc以及free函数
231 0
|
4月前
|
存储
阿里云轻量应用服务器收费标准价格表:200Mbps带宽、CPU内存及存储配置详解
阿里云香港轻量应用服务器,200Mbps带宽,免备案,支持多IP及国际线路,月租25元起,年付享8.5折优惠,适用于网站、应用等多种场景。
1399 0
|
4月前
|
存储 缓存 NoSQL
内存管理基础:数据结构的存储方式
数据结构在内存中的存储方式主要包括连续存储、链式存储、索引存储和散列存储。连续存储如数组,数据元素按顺序连续存放,访问速度快但扩展性差;链式存储如链表,通过指针连接分散的节点,便于插入删除但访问效率低;索引存储通过索引表提高查找效率,常用于数据库系统;散列存储如哈希表,通过哈希函数实现快速存取,但需处理冲突。不同场景下应根据访问模式、数据规模和操作频率选择合适的存储结构,甚至结合多种方式以达到最优性能。掌握这些存储机制是构建高效程序和理解高级数据结构的基础。
411 0
|
4月前
|
存储 弹性计算 固态存储
阿里云服务器配置费用整理,支持一万人CPU内存、公网带宽和存储IO性能全解析
要支撑1万人在线流量,需选择阿里云企业级ECS服务器,如通用型g系列、高主频型hf系列或通用算力型u1实例,配置如16核64G及以上,搭配高带宽与SSD/ESSD云盘,费用约数千元每月。
394 0
|
存储 编译器 C语言
【C语言篇】数据在内存中的存储(超详细)
浮点数就采⽤下⾯的规则表⽰,即指数E的真实值加上127(或1023),再将有效数字M去掉整数部分的1。
888 0
|
存储
共用体在内存中如何存储数据
共用体(Union)在内存中为所有成员分配同一段内存空间,大小等于最大成员所需的空间。这意味着所有成员共享同一块内存,但同一时间只能存储其中一个成员的数据,无法同时保存多个成员的值。
|
存储 C语言
数据在内存中的存储方式
本文介绍了计算机中整数和浮点数的存储方式,包括整数的原码、反码、补码,以及浮点数的IEEE754标准存储格式。同时,探讨了大小端字节序的概念及其判断方法,通过实例代码展示了这些概念的实际应用。
937 1

热门文章

最新文章