C语言进阶学习日志:动态内存分配

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: C语言进阶学习日志:动态内存分配

malloc函数:

这是在堆区上开辟空间的函数 头文件为stdlib.h

81cfae54437748b686cfa209001210da.png

根据这张图片我们可以知道 malloc函数的参数是 字节  返回类型是void * 类型 还知道这个函数开辟空间返回的是这块空间的起始地址 如果开辟空间失败 就会返回 NULL指针

所以我们在使用这个函数的时候如果没有对这个函数的返回类型做检查 那么编译器会报错 说malloc函数返回的指针可能为空 虽说这个错误是无关紧要的 没有这个错误程序也能运行 但谁也说不准它会不会开辟失败 所以还是严谨点要好

如果说参数 为0 那么malloc的行为是不确定的 这个的看编译器怎么办

int main()
{
  int* p = (int*)malloc(5*sizeof(int));//这里强转是因为malloc返回的是void* 虽然有些编译器
  if(p==NULL)                          //不转也行 但还是转一下会好一点
 {
   printf("%s",strerror(errno));
   //strerror字符串函数 在我之前的文章 字符串操作函数
 }
 free(p);
}

大家注意到我上面的代码 里面的free函数了吗 这个free函数是为了 将我们向内存申请的空间还回去 最后我们再来说这个


calloc函数:

这个和malloc函数相差不大 唯一的不同就是 这个函数开辟空间后并把这份空间的内容初始

33b2c6e7730b489aae0e13a5d147e8d1.png

#include <stdio.h>
#include <stdlib.h>
int main()
{
  int* p=(int*)calloc(5,sizeof(int));
  for(int i=0;i<5;i++)
  {
     printf("%d ",p[i]);   //打印出来的答案肯定是0 0 0 0 0
  }
}

所以calloc函数就没什么好说的了


realloc函数:

这个函数可用来调节我们开辟了的空间大小 也可以自己开辟一段空间

68038fafc10f401589553ffea7f22404.png

 通过这张图我们可以知道 它的第一个参数是malloc calloc realloc所开辟空间的首地址 ,但是如果你传进去的参数是NULL话  那么realloc函数的作用和malloc函数的作用是一样的


我们知道realloc函数也会返回一个空间的地址 那我们返回的地址应该放在哪里呢 ?是放在被重新分配大小的空间呢? 还是一份新的空间呢?

fd3099a02d8d40f688b4e9d1cb8d6cb5.gif

这个是第一种情况 我们开辟的空间后面有足够的空间  就直接在后面开辟空间返回的地址与之前相同 如果开辟失败返回NULL 

8d62a7d094224a1fabb3c082b471d6e4.gif

 这个是第二种情况后面的空间不足  则realloc会开辟一块新的空间  并把原来空间的数据拷进去同时把原来的空间释放掉 返回新空间的首地址 一样的开辟失败 还是会返回NULL


所以综合以上的两种情况我们平常在开辟空间的时候要注意开辟空间返回地址的检查 vs编译器就会这样 如果你没有对它检查就会报错  所以说这个看个人习惯  毕竟开辟失败的概率较小


free函数:

c10bd2f896bc43fc9953476f04f93a22.png


free函数是将 我们申请的空间还回去(释放掉)

有个要注意的点是 看下面的代码:>

#include <stdio.h>
int main()
{
    int* p=(int*)malloc(10*sizeof(int));//开辟十个int空间
    for(int i=0;i<5;i++)
    {
        *p=i;
        p++;
    }
    free(p);
}


大家觉得这里的 free 能把开辟的空间 free 掉嘛?

当然答案是肯定不能的 这串代码中我们开辟的空间返回的首地址放在p里面  在后面的for循环中 我们对前面五个空间 赋值 1 2 3 4 5 这个时候p指向第六个空间

这个时候是不能free掉的  我们开辟的空间是不能够free一部分的 所以我们开辟的空间返回的地址是一定要记住的

还有几个要注意的点:

① free不能free两遍

② 不能free不是动态内存的值

③ 动态开辟的内存要记得 free 掉 不然会造成内存泄漏

相关实践学习
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
目录
相关文章
|
2月前
|
存储 人工智能 搜索推荐
一种专为AI代理设计的内存层,能够在交互过程中记忆、学习和进化
Mem0 是专为 AI 代理设计的内存层,支持记忆、学习与进化。提供多种记忆类型,可快速集成,适用于开源与托管场景,助力 AI 代理高效交互与成长。
375 123
一种专为AI代理设计的内存层,能够在交互过程中记忆、学习和进化
|
3月前
|
缓存 算法 搜索推荐
从O(n²)到O(n log n):深度剖析快速排序的内存优化与cache-friendly实现 🌟 Hello,我是摘星!
作为一名深耕算法优化领域多年的技术工程师,我见证了无数次关于排序算法性能讨论的激烈辩论,而快速排序(QuickSort)始终以其卓越的实践表现占据着核心地位。今天我想和大家深入探讨的,不仅仅是快速排序的基础实现,更是如何通过精妙的内存优化策略,将其从理论上的O(n²)最坏时间复杂度,提升到实际应用中稳定的O(n log n)性能表现,并实现真正的cache-friendly设计。在我的实践经验中,许多开发者对快速排序的理解还停留在基础的递归实现层面,而忽略了现代计算机体系结构下内存层次结构对算法性能的深刻影响。本文将系统地分析快速排序在内存访问模式、缓存局部性、尾递归优化等方面的核心技术要点,
141 0
从O(n²)到O(n log n):深度剖析快速排序的内存优化与cache-friendly实现 🌟 Hello,我是摘星!
|
4月前
|
安全 C语言
C语言中的字符、字符串及内存操作函数详细讲解
通过这些函数的正确使用,可以有效管理字符串和内存操作,它们是C语言编程中不可或缺的工具。
296 15
|
7月前
|
存储 NoSQL Redis
阿里面试:Redis 为啥那么快?怎么实现的100W并发?说出了6大架构,面试官跪地: 纯内存 + 尖端结构 + 无锁架构 + EDA架构 + 异步日志 + 集群架构
阿里面试:Redis 为啥那么快?怎么实现的100W并发?说出了6大架构,面试官跪地: 纯内存 + 尖端结构 + 无锁架构 + EDA架构 + 异步日志 + 集群架构
阿里面试:Redis 为啥那么快?怎么实现的100W并发?说出了6大架构,面试官跪地: 纯内存 + 尖端结构 +  无锁架构 +  EDA架构  + 异步日志 + 集群架构
|
11月前
|
存储 编译器 程序员
【C语言】内存布局大揭秘 ! -《堆、栈和你从未听说过的内存角落》
在C语言中,内存布局是程序运行时非常重要的概念。内存布局直接影响程序的性能、稳定性和安全性。理解C程序的内存布局,有助于编写更高效和可靠的代码。本文将详细介绍C程序的内存布局,包括代码段、数据段、堆、栈等部分,并提供相关的示例和应用。
384 5
【C语言】内存布局大揭秘 ! -《堆、栈和你从未听说过的内存角落》
|
12月前
|
存储 C语言
C语言如何使用结构体和指针来操作动态分配的内存
在C语言中,通过定义结构体并使用指向该结构体的指针,可以对动态分配的内存进行操作。首先利用 `malloc` 或 `calloc` 分配内存,然后通过指针访问和修改结构体成员,最后用 `free` 释放内存,实现资源的有效管理。
1046 13
|
12月前
|
存储 编译器 数据处理
C 语言结构体与位域:高效数据组织与内存优化
C语言中的结构体与位域是实现高效数据组织和内存优化的重要工具。结构体允许将不同类型的数据组合成一个整体,而位域则进一步允许对结构体成员的位进行精细控制,以节省内存空间。两者结合使用,可在嵌入式系统等资源受限环境中发挥巨大作用。
376 12
|
11月前
|
存储 缓存 算法
【C语言】内存管理函数详细讲解
在C语言编程中,内存管理是至关重要的。动态内存分配函数允许程序在运行时请求和释放内存,这对于处理不确定大小的数据结构至关重要。以下是C语言内存管理函数的详细讲解,包括每个函数的功能、标准格式、示例代码、代码解释及其输出。
392 6
|
12月前
|
存储 C语言 开发者
C 语言指针与内存管理
C语言中的指针与内存管理是编程的核心概念。指针用于存储变量的内存地址,实现数据的间接访问和操作;内存管理涉及动态分配(如malloc、free函数)和释放内存,确保程序高效运行并避免内存泄漏。掌握这两者对于编写高质量的C语言程序至关重要。
369 11
|
12月前
|
传感器 人工智能 物联网
C 语言在计算机科学中尤其在硬件交互方面占据重要地位。本文探讨了 C 语言与硬件交互的主要方法,包括直接访问硬件寄存器、中断处理、I/O 端口操作、内存映射 I/O 和设备驱动程序开发
C 语言在计算机科学中尤其在硬件交互方面占据重要地位。本文探讨了 C 语言与硬件交互的主要方法,包括直接访问硬件寄存器、中断处理、I/O 端口操作、内存映射 I/O 和设备驱动程序开发,以及面临的挑战和未来趋势,旨在帮助读者深入了解并掌握这些关键技术。
291 6