动态内存函数详解-【malloc,calloc,realloc,free】

简介: 动态内存函数详解-【malloc,calloc,realloc,free】

667a32745c6645698e07adaf4ff84b22.png

💐 🌸 🌷 🍀 🌹 🌻 🌺 🍁 🍃 🍂 🌿 🍄🍝 🍛 🍤

📃个人主页 阿然成长日记 👈点击可跳转

📆 个人专栏: 🔹数据结构与算法🔹C语言进阶

🚩 不能则学,不知则问,耻于问人,决无长进

🍭 🍯 🍎 🍏 🍊 🍋 🍒 🍇 🍉 🍓 🍑 🍈 🍌 🍐 🍍

📋malloc

头文件:stdlib.h

一、malloc的简介

1.malloc函数的定义:

void* malloc (size_t size);

2.参数:

size: 内存块的大小(以字节为单位)。size是无符号整型。size_t

3.返回值:

1)如果开辟成功,则返回一个指向开辟好空间的指针

2)如果开辟失败,则返回一个NULL指针,因此malloc的返回值一定要做检查。

3)返回值的类型是 void* ,所以malloc函数并不知道开辟空间的类型,具体在使用的时候使用者自己来决定

4)如果参数 size 为0,malloc的行为是标准是未定义的,取决于编译器。

4.功能:

向内存申请一块连续可用的空间,并返回指向这块空间的指针。单位:字节

二、malloc函数的使用

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
int main()
{
  int* p = (int*)malloc(40);//申请了40个字节,强转成int*型
  if (p == NULL)//判断是否开辟成功
  {
    perror(malloc);
    return 1;
  }
  //打印开辟空间,检验是否开辟完成
  int i = 0;
  for (i = 0;i < 10; i++)
  {
    printf("%p\n", (p + i));
  }
  free(p);
  p=NULL;
  return 0;
}

运行截图:

可以看到,我们已经开辟了十个整形的空间。

📄 free函数

头文件:stdlib.h

free函数的简介

void free (void* ptr);

参数:指向先前分配的内存块的指针

如果参数 ptr 指向的空间不是动态开辟的,那free函数的行为是未定义的。

如果参数 ptr 是NULL指针,则函数什么事都不做。

没有返回值

free函数使用注意事项

如果开辟的空间使用完了,则应该使用free函数将p所指向的空间释放掉。

注意:,p是指针变量,有自己存储空间和内容,我们free释放的只是p指向的那块空间,p并没释放,他仍然指向那块空间,所以需要手动给p=NULL。

📜calloc

头文件:stdlib.h

calloc函数的简介

void* calloc (size_t num, size_t size);

参数

1.*num*:要分配的元素数

2.size:要分配的元素类型

返回值

1.成功时,指向函数分配的内存块的指针

(此指针的类型始终为 ,可以强制转换为所需类型的数据指针,以便可取消引用。)

2.如果函数无法分配请求的内存块,则返回空指针。void*

功能

–>.函数的功能是为 num 个大小为 size 的元素开辟一块空间,并且把空间的每个字节初始化为0

区别:与函数 malloc 的区别只在于 calloc 会在返回地址之前把申请的空间的每个字节初始化为全0

二、calloc函数的使用

#include<stdio.h>
#include<stdlib.h>
int main()
{
  int* p = (int*)calloc(10,sizeof(int));//申请了40个字节,强转成int*型
  if (p == NULL)//判断是否开辟成功
  {
    perror(malloc);
    return 1;
  }
  //打印开辟空间,检验是否开辟完成
  int i = 0;
  for (i = 0;i < 10; i++)
  {
    printf("%p\n", (p + i));
  }
  free(p);
  p = NULL;
}

calloc函数的注意事项

1.不能申请开辟空间太大

#include<stdio.h>
#include<stdlib.h>
int main()
{
  int* p = (int*)calloc(INT_MAX,sizeof(int));//申请了40个字节,强转成int*型
  if (p == NULL)//判断是否开辟成功
  {
    perror(calloc);
    return 1;
  }
  //打印开辟空间,检验是否开辟完成
  int i = 0;
  for (i = 0;i < 10; i++)
  {
    printf("%p\n", (p + i));
  }
  free(p);
  p = NULL;
}

显示错误:Not enough space

📉 realloc函数

一、realloc函数的简介

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

1.参数

ptr:指向先前分配有 、 或 的内存块的指针。

或者,这可以是一个空指针,在这种情况下,将分配一个新块(就像被调用一样)

size:内存块的新大小(以字节为单位)。是无符号整型。size_t

(size=原来+新增加)

2.返回值:指向重新分配的内存块的指针,该内存块可能与新位置相同也可能是新位置

3.功能:(1)重新分配内存块,更改指向的内存块的大小。

(2).如果函数无法分配请求的内存块,则返回空指针,并且不会释放参数指向的内存块

(3).有时会我们发现过去申请的空间太小了,有时候我们又会觉得申请的空间过大了,那为了合适的内存,我们一定会对内存的大小做灵活的调整。那 realloc 函数就可以做到对动态开辟内存大小的调整。

二、realloc使用

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
int main()
{
  int* p = (int*)calloc(10,sizeof(int));//申请了40个字节,强转成int*型
  if (p == NULL)//判断是否开辟成功
  {
    perror(calloc);
    return 1;
  }
  //打印开辟空间,检验是否开辟完成
  int i = 0;
  for (i = 0;i < 10; i++)
  {
    p[i]=i+1;
  }
  int* ptr = (int*)realloc(p, 80);
  if (ptr != NULL)
  {
    p = ptr;
  }
  else
  {
    perror(realloc);
    return 1;//结束
  }
  for (i = 0; i < 20; i++)
  {
    printf("%d\n", p[i]);
  }
  free(p);
  p = NULL;
}

三、realloc函数的注意事项

用上面代码为例

1.使用realloc给p扩容后,不能直接用p来接收。因为一旦扩容失败,将会返回NULL,那么p所指向的内容就会直接找不到了,造成内存泄漏。应该使用一个新指针ptr来接收,判断是否扩容成功后,再将ptr指向p即可。如下:

2.free(p);就相当也释放了ptr指针。因为ptr指向了p指针。

(1)扩容成功情况

int* ptr = (int*)realloc(p, 80);
  if (ptr != NULL)
  {
    p = ptr;
  }

可以看到ptr和p的值相同,说明它们指向相同。即扩容成功。

(2)扩容失败情况

我们这扩容到8000000000000直接则失败。

可以见到ptr指针指向空,也说明了realloc函数开辟失败返回值是NULL。

四、关系

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

1.realloc函数的参数,如果ptr传空指针,就相当于malloc函数。

各位看官老爷,咱下回再见!

别忘了点赞关注加评论哟

💙 💜 ❤️ 💚 💔 💓 💗 💕 💞 💘 💖 ✨ ⭐️ 🌟



相关文章
|
12天前
|
存储 编译器 程序员
【C/C++】动态内存管理(C:malloc,realloc,calloc,free)
探索C++与C语言的动态内存管理:从malloc到new/delete,了解内存分布及栈、堆的区别。文章涵盖malloc、realloc、calloc与free在C中的使用,强调内存泄漏的风险。C++引入new和delete,支持对象构造与析构,还包括operator new和placement-new。深入分析内存管理机制,揭示C与C++在内存处理上的异同。别忘了,正确释放内存至关重要!
|
17天前
|
Java 程序员 Linux
探索C语言宝库:从基础到进阶的干货知识(类型变量+条件循环+函数模块+指针+内存+文件)
探索C语言宝库:从基础到进阶的干货知识(类型变量+条件循环+函数模块+指针+内存+文件)
19 0
|
17天前
|
程序员 C语言
C语言内存管理:malloc、calloc、realloc与free函数详解
C语言内存管理:malloc、calloc、realloc与free函数详解
13 0
|
29天前
|
消息中间件 存储 Kafka
实时计算 Flink版产品使用问题之 从Kafka读取数据,并与两个仅在任务启动时读取一次的维度表进行内连接(inner join)时,如果没有匹配到的数据会被直接丢弃还是会被存储在内存中
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
|
5天前
|
存储 Java 程序员
Java面试题:方法区在JVM中存储什么内容?它与堆内存有何不同?
Java面试题:方法区在JVM中存储什么内容?它与堆内存有何不同?
26 10
|
1天前
|
存储 分布式计算 Hadoop
HadoopCPU、内存、存储限制
【7月更文挑战第13天】
24 14
|
21天前
|
存储 Java C++
Java虚拟机(JVM)管理内存划分为多个区域:程序计数器记录线程执行位置;虚拟机栈存储线程私有数据
Java虚拟机(JVM)管理内存划分为多个区域:程序计数器记录线程执行位置;虚拟机栈存储线程私有数据,如局部变量和操作数;本地方法栈支持native方法;堆存放所有线程的对象实例,由垃圾回收管理;方法区(在Java 8后变为元空间)存储类信息和常量;运行时常量池是方法区一部分,保存符号引用和常量;直接内存非JVM规范定义,手动管理,通过Buffer类使用。Java 8后,永久代被元空间取代,G1成为默认GC。
24 2
|
25天前
|
存储
数据在内存中的存储(2)
数据在内存中的存储(2)
27 5
|
25天前
|
存储 小程序 编译器
数据在内存中的存储(1)
数据在内存中的存储(1)
31 5
|
25天前
|
存储 安全 Java
SpringSecurity6从入门到实战之初始用户如何存储到内存
Spring Security 在 SpringBoot 应用中默认使用 `UserDetailsServiceAutoConfiguration` 类将用户信息存储到内存中。当classpath有`AuthenticationManager`、存在`ObjectPostProcessor`实例且无特定安全bean时,此配置生效。`inMemoryUserDetailsManager()`方法创建内存用户,通过`UserDetails`对象填充`InMemoryUserDetailsManager`的内部map。若要持久化到数据库,需自定义`UserDetailsService`接口实