C语言内存

C语言——动态内存 大家好!我是保护小周,本期为大家带来超详细的C语言——动态内存管理,论动态内存在C++/C中的重要性,学好动态内存约等于看穿了C语言~确定不来看看嘛 ~ 1.为什么存在动态内存 2.动态内存函数的介绍 3.常见的动态内存错误 4.经典笔试题 5.柔性数组 快来跟我一起学习吧! ...... 阅读详情

一.几个概念

全局变量(外部变量):出现在代码块{}之外的变量就是全局变量。
局部变量(自动变量):一般情况下,代码块{}内部定义的变量就是自动变量,也可使用auto显示定义。
静态变量:是指内存位置在程序执行期间一直不改变的变量,用关键字static修饰。代码块内部的静态变量只能被这个代码块内部访问,代码块外部的静态变量只能被定义这个变量的文件访问。

二.内存四区

代码区------程序被操作系统加载到内存的时候,所有的可执行代码(程序代码指令、常量字符串等)都加载到代码区,这块内存在程序运行期间是不变的。代码区是平行的。函数也是代码的一部分,故函数都被放在代码区,包括main函数。

静态区------全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 - 程序结束后有系统释放

栈区---------栈(stack)是一种先进后出的内存结构,由编译器自动分配内存。存放函数的参数值,局部变量的值等。栈区在程序运行期间是可以随时修改的。当一个自动变量超出其作用域时,自动从栈中弹出。
每个线程都有自己专属的栈;
栈是从高地址向低地址方向增长,其最大尺寸固定,超出则引起栈溢出;
变量离开作用域后栈上的内存会自动释放。
使用栈来实现的局部变量定义时未初始化,则变量值是随机数。
语句int a=15;C语言在编译时会转成
int a;
a=15;
不能将一个栈变量的地址通过函数的返回值返回

堆区------堆(heap)和栈一样,也是一种在程序运行过程中可以随时修改的内存区域。一般比较复杂的数据类型都是放在堆中,一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,

可以通过函数返回一个堆地址,但记得一定用通过free函数释放申请的堆内存空间,不释放会出现内存泄漏

三.堆和栈区别

(1)申请方式
stack:
由系统自动分配。例如,声明在函数中一个局部变量 int b; 系统自动在栈中为b开辟空间
heap:
需要程序员自己申请,并指明大小,在c中malloc,free函数

(2)申请后系统的响应
栈:只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出。
堆: 首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲 结点链表中删除,并将该结点的空间分配给程序,另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样,代码中的free语句才能正确的释放本内存空间。另外,由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中。

(3)申请大小的限制及生长方向
栈-------在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小 。
堆-------堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。

(4)申请效率的比较:
栈由系统自动分配,速度较快。但程序员是无法控制的。
堆是由malloc分配的内存,一般速度比较慢,而且容易产生内存碎片,不过用起来最方便.
char *p1 = (char *)malloc(10); 其中malloc申请的内存在堆区,但是变量p1在栈区,所以要调用堆区的内容,得先调用栈区内容。
另外,在WINDOWS下,最好的方式是用VirtualAlloc分配内存,他不是在堆,也不是在栈是直接在进程的地址空间中保留一快内存,虽然用起来最不方便。但是速度快,也最灵活。

(5)堆和栈中的存储内容
栈------在函数调用时,第一个进栈的是主函数中后的下一条指令(函数调用语句的下一条可执行语句)的地址,然后是函数的各个参数(在大多数的C编译器中参数是由右往左入栈的),然后是函数中的局部变量。注意静态变量是不入栈的。当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主函数中的下一条指令,程序由该点继续运行。
堆------一般是在堆的头部用一个字节存放堆的大小。堆中的具体内容有程序员安排。

最后:操作系统在管理内存时,最小单位不是字节,而是内存页(32位操作系统的内存页一般是4K)。比如,初次申请1K内存,操作系统会分配1个内存页,也就是4K内存。因为:内存页越大,内存浪费越多,但操作系统内存调度效率高,不用频繁分配和释放内存。

C语言实现内存池 什么是内存池,这里简单介绍一下(不做详细说明),内存池技术是一种用于分配大量大小相同的小对象的技术,通过该技术可以极大加快内存分配/释放过 程。其原理是先申请一大块内存,然后分成若干个大小相等的小块,用链表的方式将这些小块链在一起,当开发人员需要使用内存时(分配),从链表头取下一块返 回给开发人员使用;当开发人员使用完毕后(释放),再将这块内存重新挂回链表尾。这样操作的好处有如下三点:1、提高分配和释放的效率;2、避免开发人员 忘记释放内存造成内存泄露;3、减少内存占用(频繁的malloc是很占内存空 阅读详情

相关推荐

关于C语言中内存的理解

今天上朱老师的课又学到了很多新东西 老师对内存的讲解令我茅塞顿开。 加油冲冲冲! 在这里发个笔记记一下自己的学到的东西。 **关于内存这个大话题** 四-1 内存这个大话题 1.程序运行为什么需要内存? 1.1 计算机程序运行的目的 程序运行目的是为了去运行数据。 计算机程序= 代码+ 数据(经过运行)=结果,程序运行是为了得到一定的结果。计算机就是用来计算的,所有的计算机程序其实都是 在做计算。计算就是在计算数据。所以计算机程序中很重要的部分就是数据。 从宏观上来理解,代码就是动作,就是

weixin_49035076的博客 1396

C语言的内存分配{静态内存&动态内存&堆栈}

除此之外,c语言还允许建立内存动态分配区域,以存放一些临时用的数据,这些数据不必在程序的声明部分定义,也不必等到函数结束时才释放,而是需要时随时开辟,不需要是随时释放。通常是用于那些在编译期间就能确定存储大小的变量的存储区,但它用于的是在整个程序运行期间都可见的全局变量和静态变量。静态全局变量则限制了其作用域,即只在定义该变量的源文件内有效,在同一源程序的其它源文件中不能使用它。所有的函数外部定义的变量,它的作用域是整个程序,也就是所有的源文件,包括.c和.h文件。已初始化的静态变量存放在.data段。..

xiandang8023的博客 1万+

C 语言编程 — 内存操作

目录 文章目录目录前文列表堆、栈内存管理动态分配内存重新调整内存的大小和释放内存 前文列表 《程序编译流程与 GCC 编译器》 《C 语言编程 — 基本语法》 《C 语言编程 — 基本数据类型》 《C 语言编程 — 变量与常量》 《C 语言编程 — 运算符》 《C 语言编程 — 逻辑控制语句》 《C 语言编程 — 函数》 《C 语言编程 — 高级数据类型 — 指针》 《C 语言编程 — 高级数据类...

烟云的计算 6330

【C语言】内存你知多少?详解C语言动态内存管理

谈谈我们经常用的内存动态内存管理

菜菜成长为后端开发大佬 1691

TCP Reno/CUBIC 拥塞控制算法对比:从 Tahoe 到 BBR 的 4 种核心策略演进

本文深入解析了TCP拥塞控制算法的演进历程,从经典的Tahoe、Reno到现代的CUBIC和BBR,详细对比了4种核心策略的实现机制与性能差异。通过分析拥塞窗口、流量控制等关键技术,揭示了不同算法在高带宽延迟网络中的优化方向,为网络协议栈优化提供理论依据和实践指导。

weixin_33725239的博客 440

Oracle-如何修复undo坏快

undo出现坏快,导致数据库宕机,无法启动

qqqyyy0422的博客 570

C语言的内存知识

这节我们主要认识一下内存,便于理解指针操作和后续内存管理。

Stark的博客 2381

Weblogic安装与部署

27.免密登录,在目录Oracle\Middleware\Oracle_Home\user_projects\domains\base_domain\servers\AdminServer和Oracle\Middleware\Oracle_Home\user_projects\domains\base_domain\servers\Server-TA目录下,新建security\boot.properties文件,13.点击新建按钮,填写服务器名称,服务器监听地址,再点击下一步,最后点击完成。

m0_46259466的博客 6635

C语言——内存管理

C语言中,内存管理需要对静态和动态内存分配,静态分配在编译时确定,而动态分配(如malloc, calloc, realloc)则在运行时进行,需程手动管理,包括适时释放(用free)以避免内存泄漏。同时,了解栈、堆、数据区、代码区等内存区域的特性和用途,对于有效管理内存至关重要。

脑壳有点痒,好像要长脑子了! 4547

树莓派通过TTL3.3转485 Modbus采集水表

所需道具 树莓派0,我用的是树莓派zero wh; 具有光电直读功能的有线水表,我用的是咸鱼淘的埃美柯LXSY-20E1; TTL3.3 转 485模块,带隔离的贵些; 5V转12V升压模块。 原理 树莓派有UART(GPIO14 Tx 和 GPIO15 Rx)串口通讯功能,电器特性是3.3V TTL,直读远传水表支持M-Bus/485通讯接口,我买的光电直读水表485要求12V供电(根据仪表厂家说明书)。TTL和485虽然都是串口通讯,但电器特性不一样,不能直接接!我已经烧掉一个树莓派...

xhydongda的博客 3443

【5G NB-IoT NTN】3GPP R17 NB-IoT NTN介绍_nbiot ntn

在3GPP R17协议中,将NB-IoT集成到了NTN(非陆地网络,即卫星通信)中,并定义了一个系统架构。在这个架构中包括一个可配置再生payload的低轨道(LEO)卫星,这意味着该卫星可以执行传统基站的全部或部分功能。该系统架构还可以适配同步轨道(GEO)卫星,这些卫星与LEO卫星类似,也可以配置再生payload。系统高度范围轨道波束覆盖范围LEO300~1500km绕地球转100~1000kmGEO35786km与地球自转同步200~3500km。

2401_84010302的博客 3568

C/C++内存管理,malloc,realloc,calloc,new,delete详解!!!

new和delete在面对自定义类型时会去调用构造函数和析构函数new =先开空间 再调用构造函数delete = 先调用析构函数 再释放空间public:~Stack()_top = 0;int _top;int main()//new先开空间 再去调用构造函数delete(p2);//delete先调用析构函数,再去释放空间return 0;如果需要开10个Stack类型的空间 用new[] 和 delete[]

qq_73955920的博客 1717

YOLOv8改进策略【Conv和Transformer】| CVPR-2023 BiFormer 稀疏自注意力,减少内存占用

本文记录的是利用双级路由注意力机制优化的目标检测网络模型。传统的复杂度高,随着输入空间分辨率增加,计算量呈平方增长,导致严重的可扩展性问题。而本文所使用的在获取全局信息的同时,通过区域到区域路由和令牌到令牌注意力的合理设计,减少了不必要的计算量。BiFormer: Vision Transformer with Bi-Level Routing Attention采用四阶段金字塔结构,与一些先进的视觉Transformer类似。在每个阶段,首先使用重叠的补丁嵌入(在第一阶段)或补丁合并模块(在第二到第四阶段

Limiiiing的博客 614

C语言的内存函数

C语言库函数中有可以直接对内存操作的函数,这类函数叫作内存函数。内存函数即针对内存块进行数据处理的函数,内存块的意思就是“一块内存,一块空间”。

2401_85409229的博客 1608

知识图谱大模型系列之 12 LLM 知识图谱构建器:从零到 GraphRAG 使用 LLM 知识图谱生成器在 GenAI 应用中提取和使用知识图谱(教程含源码)

为了更深入地了解 LLM 知识图谱构建器,GitHub 存储库提供了大量信息,包括源代码和文档。此外,我们的文档提供了详细的入门指南,而GenAI 生态系统则提供了有关可用更广泛工具和应用程序的进一步见解。

iCloudEnd的博客 2037

[VCS]门级仿真及SDF反标

摘要:门级仿真在STA工具普及后仍是验证的重要环节,主要用于检查SDC完备性、异步电路时序、网表完整性及为功耗分析提供波形。门级仿真分为不带时序反标的前仿和带SDF反标的后仿,后仿需加载SDF文件提供精确延时信息。VCS提供多种仿真选项控制时序检查行为,SDF反标可通过命令或系统函数实现。后仿需特别注意关闭notimingcheck选项以确保时序检查有效性,并建议检查SDF反标报告和波形验证延时一致性。

元直的博客 9790

C语言内存函数

本文详细讲解了C语言中四种内存操作函数:memcpy、memmove、memset和memcmp。memcpy用于内存块拷贝,不处理重叠区域;memmove功能类似但可处理重叠内存;memset以字节为单位设置内存内容;memcmp比较两块内存内容。文章从语法形式、使用示例到模拟实现三个层次展开……

Y409001的博客 2352

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

C语言的内存

程序写好编译后保存在磁盘,然后加载到内存中运行的,一名合格的程序员必须了解内存,学习C语言更是要多了解些内存的知识点,C语言是一门偏向硬件的编程语言。

qq_33406021的博客 1263

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

【C语言】内存函数

本文深入解析C语言中四个核心内存操作函数:memcpy、memmove、memset和memcmp。memcpy实现基础内存拷贝但不处理重叠内存;memmove是其增强版,支持内存重叠场景;memset按字节设置内存值;memcmp按字节比较内存内容。文章通过函数说明、实用示例和模拟实现三个维度,详细讲解各函数的特点和使用场景,帮助读者掌握C语言内存操作的精髓,避免常见陷阱。理解这些函数的底层实现逻辑,能更好地运用C语言"直面内存"的特性进行高效开发。

2301_78257800的博客 1383

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

C语言 内存函数

memcpy 是C语言标准库函数,用于在内存中复制数据块,在 <string.h> 头文件中声明。以下是memmove 是C 语言标准库函数,用于安全复制内存块,声明于 <string.h> 头文件。以下是详细memset 是C 语言标准库函数,用于初始化内存块,声明于 <string.h> 头文件。以下是详细说memcmp 是 C语言标准库函数,用于比较两个内存块的二进制数据,声明于 <string.h> 头文件。

2401_88465894的博客 1568

【C语言】内存管理

动态内存分配malloc、calloc;重新调整内存的大小realloc;释放内存free

v13111329954的博客 2155

C语言——内存问题

C语言——内存问题 c语言内存模块会出现很多问题,本文总结了c语言可能出现的内存问题、问题示例以及避免内存问题的方法。

小矮子不怕艾的博客 3515
上一篇: C语言特点
下一篇: 从C语言到C++
Hello_World_10
博客等级 码龄8年 8粉丝 11原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值