内存管理函数malloc,calloc,realloc详解

简介: 内存管理函数malloc,calloc,realloc详解

1.malloc

当我们想开辟一块动态内存空间的时候,就需要使用动态内存函数了,比如

char* p;

当我们想要使用地址p下的内存时,就需要用到malloc函数

void* malloc(size_t size);

注意,malloc函数的返回类型是(void*),形参是要开辟空间的字节数。所以要使用malloc这个函数,必须将返回值强制类型转换为想要的类型,比如

1. char* p1=(char*)malloc(10);//在p1这个地址下开辟10个字节空间,可以存放10个char型数据
2. int* p2=(int*)malloc(20);//在p2这个地址下开辟20个字节空间,可以存放5个int型数据

注意,malloc函数开辟内存空间有时会开辟失败,这时会返回空指针(NULL),所以,要较好的使用malloc函数,还要检查一下是否成功开辟内存,代码如下

1. int* p=(int*)malloc(20);//开辟内存空间
2. if(p==NULL)
3. {
4. printf("%s",strerror(errno));//打印开辟失败的原因
5. }

需要知道的是,malloc函数开辟的内存空间不会自动初始化,里面放的是随机值

1.  int* p = (int*)malloc(20);//开辟内存空间
2.  if (p == NULL)
3.  {
4.    printf("%s", strerror(errno));//打印开辟失败的原因
5.  }
6.  else
7.  for (int i = 0; i <5 ; i++)//访问新开辟的内存
8.  {
9.    printf("%d", (int)*(p + i));
10.   }

结果如下

malloc函数算是讲完了,但有一个非常重要的点并没有提到。我们知道创建一个数组相当于向内存空间申请了连续的一块空间,数组申请的内存空间是在栈上的,数组离开作用域会自动销毁,释放内存。

但是这里用malloc函数申请的内存空间是在堆上的,出作用域不会销毁,必须手动释放内存,否则会造成内存泄漏!(即使退出程序OS会自动回收内存,还是要有手动释放的好习惯)

手动释放内存需要使用free函数,free函数会把开辟的内存释放,内存的首地址就会变成野指针,所以还要将首地址置为空。代码如下

1. int* p = (int*)malloc(20);//开辟内存空间
2.  if (p == NULL)
3.  {
4.    printf("%s", strerror(errno));//打印开辟失败的原因
5.  }
6. //使用
7. 
8. //手动释放空间
9.  free(p);
10.   p = NULL;

2.calloc

不同于malloc的是,calloc函数会自动将新开辟的内存空间初始化为全0

void* calloc(size_t num,size_t size);

size_t num:开辟的个数

size_t size:开辟的类型大小

例如,开辟5个整型空间

1. #include<stdlib.h>
2. #include<errno.h>
3. #include<string.h>
4. #include<stdio.h>
5. int main()
6. {
7.  int* p = (int*)calloc(5,4);//开辟内存空间
8.  if (p == NULL)
9.  {
10.     printf("%s", strerror(errno));//打印开辟失败的原因
11.   }
12.   else
13.     //使用
14. 
15.   free(p);
16.   p = NULL;
17.   return 0;
18. }
19.

3.realloc

realloc函数用于原开辟的空间不足的情况下开辟更大的空间

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

void* ptr:原空间首地址

size_t size:新空间字节大小

realloc函数开辟新的空间会遇到两种情况

  1. 原空间后面空间充足,在原空间后面继续开辟新的空间,返回的地址和原地址相同。
  2. 原空间后面空间不足:
  • realloc会找到更大的空间
  • 将原来的数据拷贝到新的空间
  • 释放旧的空间
  • 返回新空间的地址(不同于原地址)
1. #include<stdlib.h>
2. #include<errno.h>
3. #include<string.h>
4. #include<stdio.h>
5. int main()
6. {
7.  int* p = (int*)calloc(5,4);//开辟内存空间
8.  if (p == NULL)
9.  {
10.     printf("%s", strerror(errno));//打印开辟失败的原因
11.   }
12.   else
13.     //使用
14.     for (int i = 0; i < 5; i++)
15.     {
16.       printf("%d ", *(p + i));
17.     }
18.   p=realloc(p, 40);//扩大内存空间,将20字节增到40字节
19.   for (int i = 0; i < 10; i++)
20.   {
21.     printf("%d ", *(p + i));
22.   }
23.   free(p);
24.   p = NULL;
25.   return 0;
26. }

 

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