C语言程序的内存布局

C语言数据存储——字节、地址、端序 文章目录高低字节操作数截断高低地址大小端序内存中使用小端序存储 高低字节 高低字节与内存中的位置无关,描述的是数据中字节的权。例如 int a = 0x00000159; 01 这个字节为高字节,59这个字节为低字节,原因是01所处的位置权较大,而59所处位置的权较小。 简言之,字节从左到右,从高到低 操作数截断 当把字节多的类型数据赋给一个占字节较少的变量时,会发生截断 就是只保留所能保留的原数据的低字节 如 将int(4字节) 赋给char(1字节),那么数据就只会截断最后的1个字节,高位字节舍去。 阅读详情
        我们做C语言中这么多年,都知道这样一句话,C语言代码形成可执行程序,需要经过编译->汇编->链接三个阶段。背都背熟了,但是到底啥意思,每一步都会产生一些什么东西,很多人都不是太了解。今天就详细的来说说这个问题:

        先看下图,在这个图中,我详细的描述了,整个过程及中间的一些步骤:

        

        代码段,只读数据段,读写数据段,未初始化数据段属于静态区域。栈和堆属于动态区域。代码段,只读数据段和读写数据段将在连接之后产生,未初始化数据段将在程序初始化的时候开辟,而堆和栈将在程序的运行中分配和释放。

       

        C语言程序分为映像和运行两种状态。在编译连接后形成的映像中,将只包含代码段,只读数据段和读写数据段。在程序运行之前,将动态生成未初始化数据段,在程序的运行时还将动态形成堆和栈区域。
        而上面的程序呢, 最终都会转化为内存中的都会放置在内存中运行,程序的几个段,最终也几个区域。C语言可执行程序的内存布局如下图所示:

        

        在内存中,从低地址到高地址,依次是只读段,读写段,未初始化段,堆,栈段。这只是一种内存分布,并没有考虑到实际系统的情况。在实际的系统中,程序有载入和运行两个概念。嵌入式系统有两种内存,一种是可以固化只读的内存(如ROM,Nor Flash),另一种是易失的可读写的内存(SRAM和SDRAM)。程序中的各个段也有需要固化和需要读写的。程序中的各个段必须载入到内存的恰当位置,程序才可以运行。C语言中各部分需要固化和可写的情况如下表:

        

        一般情况下,经过编译后的程序存储在Flash或这硬盘中,在运行时需要将程序加载到RAM中。嵌入式系统的Nor Flash和硬盘还有一定的差别,在硬盘的程序必须加载到RAM中才可以运行,但是在Nor Flash中的程序可以通过XIP的方式运行。
说了这么多,说了最后可执行文件的结构分配,说了存储方式,这里我还是忍不住说一些static的话题了:
        静态变量说明符是static。 静态变量是静态存储方式,但是属于静态存储方式的量不一定就是静态变量。 例如外部变量虽属于静态存储方式,但不一定是静态变量,必须由static加以定义后才能成为静态外部变量,或称静态全局变量。
        1)静态局部变量:它在函数内定义,它的生存期为整个源程序,但是其作用域仍与自动变量相同,只能在定义该变量的函数内使用该变量。退出该函数后, 尽管该变量还继续存在,但不能使用它。
        2)允许对构造类型静态局部量赋初值  例如数组,若未赋以初值,则由系统自动赋以0值。
        3)对基本类型的静态局部变量若在说明时未赋以初值,则系统自动赋予0值。而对自动变量不赋初值,则其值是不定的。 根据静态局部变量的特点, 可以 看出它是一种生存期为整个源程序的量。虽然离开定义它的函数后不能使用,但如再次调用定义它的函数时,它又可继续使用, 而且保存了前次被调用后留下的值。 因此,当多次调用一个函数且要求在调用之间保留某些变量的值时,可考虑采用静态局部变量。虽然用全局变量也可以达到上述目的,但全局变量有时会造成意外的副作用,因此仍以采用局部静态变量为宜。
        4)静态全局变量:全局变量(外部变量)的说明之前再冠以static 就构成了静态的全局变量。全局变量本身就是静态存储方式, 静态全局变量当然也是静态存储方式。 这两者在存储方式上并无不同。这两者的区别虽在于非静态全局 变量的作用域是整个源程序,           当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。 而静态全局变量则限制了其作用域, 即只在定义该变量的源文件内有效, 在同一源程序的其它源文件中不能使用它。由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用, 因此 可以避免在其它源文件中引起错误。从以上分析可以看出, 把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量改变为静态变量后是改变了它的作用域, 限制了它的使用范围。
当一个源程序由多个源文件组成时,C语言根据函数能否被其它源文件中的函数调用,将函数分为内部函数和外部函数:
        1)内部函数(又称静态函数):在一个源文件中定义的函数,只能被本文件中的函数调用,而不能被同一程序其它文件中的函数调用。定义一个内部函数,只需在函数类型前再加一个“static”关键字即可
正因为此,所以内部函数又称静态函数。但此处“static”的含义不是指存储方式,而是指对函数的作用域仅局限于本文件。
使用内部函数的好处是:不同的人编写不同的函数时,不用担心自己定义的函数,是否会与其它文件中的函数同名,因为同名也没有关系。
        2 )外部函数:在定义函数时,如果没有加关键字“static”,或冠以关键字“extern”,表示此函数是外部函数:
        [extern]  函数类型  函数名(函数参数表)
        {……}
        调用外部函数时,需要对其进行说明:
        [extern]  函数类型  函数名(参数类型表)[,函数名2(参数类型表2)……];


C语言内存精讲,让你彻底明白C语言的运行机制! (先打开一个程序在计算机中到底是如何运行的.html) 2. 虚拟内存到底是什么?为什么我们在C语言中看到的地址是假的? 3. 虚拟地址空间以及编译模式 4. C语言内存对齐,提高寻址效率 5. 内存分页机制,完成虚拟地址的映射 6. 分页机制究竟是如何实现的? 7. MMU部件以及对内存权限的控制 8. Linux下C语言程序的内存布局(内存模型) 9. Windows下C语言程序的内存布局(内存模型) 10. 用户模式和内核模式 11. 栈(Stack)是什么?栈溢出又是怎么回事? 12. 一个函数在栈上到底是怎样的? 13. 函数调用惯例(Calling Convention) 立即下载

相关推荐

C语言编程程序的内存如何布局

本文教你C语言编程程序的内存是如何布局。

C++并发编程(六):内存顺序

原子操作的内存顺行 有六个内存顺序选项可应用于对原子类型的操作:memory_order_relaxed, memory_order_consume, memory_order_acquire, memory_order_release, memory_order_acq_rel, 以及memory_order_seq_cst。除非你为特定的操作指定一个顺序选项,否则内存顺序选项对于所有原子类型...

qq_33215865的博客 3967

JOOQ用法和实例

jOOQ,是一个ORM框架,利用其生成的Java代码和流畅的API,可以快速构建有类型约束的安全的SQL语句。jOOQ的核心优势是可以将数据库表结构映射为Java类,包含表的基本描述和所有表字段。通过jOOQ提供的API,配合生成的Java代码,可以很方便的进行数据库操作生成的Java代码字段类型是根据数据库映射成的Java类型,在进行设置和查询操作时,因为是Java代码,都会有强类型校验,所以对于数据的输入,是天然安全的,极大的减少了SQL注入的风险。

m0_67403076的博客 1377

c语言程序内存地址分布

一个程序(进程)有4G内存的虚拟内存地址空间。 sizeof(指针)==4 0~3G 用户空间,3G–4G 内核空间 从低地址到高地址: 用户空间(代码区–>数据区–>BBS–>堆区–>堆栈缓冲区–>栈区)–>内核空间! 我们先来看看不同的部分都有什么作用: 代码区: 存储代码文本,字面值。这一部分的值是不能被修改,只要修改代码区的内容,就会出现段错误(核心已...

weixin_45828158的博客 1010

Vivado 2018.3实战:用IDELAYE3和ISERDESE3搞定高速ADC数据采集(附仿真源码)

本文详细介绍了在Vivado 2018.3中使用Xilinx UltraScale架构的IDELAYE3和ISERDESE3原语实现高速ADC数据采集的实战方法。通过分析5GHz采样系统的时序挑战,提供从PCB布局到Vivado实现的完整解决方案,包括精密时序校准、多相位数据重组及系统级调试技巧,并附赠仿真源码助力工程师快速掌握高速数据采集技术。

weixin_30567225的博客 582

YOLOv8n模型导出ONNX的避坑指南:解决版本差异,正确生成TensorRT/RKNN所需输出节点

本文详细介绍了YOLOv8n模型导出ONNX格式的实战避坑指南,涵盖版本差异处理、代码修改技巧及TensorRT/RKNN部署优化方案。针对不同推理框架需求,提供输出节点生成、动态轴处理和后处理划分等核心问题的解决方案,帮助开发者高效完成模型部署。

weixin_33247358的博客 357

c程序在虚拟内存中的地址顺序

c程序在虚拟内存中的地址从低地址到高地址的顺序依次是: text段(代码区)、.rodata段(常量区)、.data段(已初始化的全局变量区)、.bss段(未初始化的全局变量区)、堆、动态库映射区、栈、内核区(用户态代码不可访问) BSS段:(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域。BSS是英文Block Started by Symbol的

u011081315的专栏 899

YIUI框架深度解析:基于ET的数据驱动UI开发实践

在Unity游戏开发中,UI管理是构建复杂应用的核心挑战之一。传统命令式编程需要开发者手动操作每个UI组件,导致业务逻辑与视图层高度耦合,代码难以维护。数据驱动是一种先进的架构思想,它通过建立数据模型与UI组件之间的绑定关系,实现数据变化时UI的自动更新,从而将开发者的关注点从“如何操作UI”转移到“数据状态是什么”。这种模式显著提升了代码的可维护性和开发效率,尤其适用于状态频繁变化的游戏界面。YIUI框架正是这一思想在Unity UGUI上的工程化实践,它通过Model-View-Component的清晰

java天气 431

C语言程序内存布局

一、几个概念 1.栈(stack)       C语言通过栈来维护函数调用上下文,也就是说C中的函数、函数参数列表、局部变量、函数返回值都保存在栈内存中,在完成函数调用之后栈帧随即销毁,至于具体的压栈顺序和上下文维护工作由谁来完成,则取决于函数的调用方式(cdecl/stdcall/fastcall/pascal).       栈帧一般包括如下几方面内容:       ①函数的参数列表和

super_bert的专栏 4874

PLC期末速成——顺序功能图转梯形图

一、根据顺序功能图写出梯形图程序 顺序功能图: 梯形图: 1、程序段1,系统运行标志M0.0的启-保-停控制电路。 2、程序段2,PLC上电与逆行,初始化脉冲M1.0激活初始化步M2.0。 3、程序段3,当M2.0初始化步为活动步,并且M0.0系统运行标志位为1时,置位M2.1步,复位M2.0步。 4、当M2.1为活动步,并且I0.3中液位传感器为1时,置位M2.2步,复位M2.1步。 5、程序段5,当M2.2为活动步,并且I0.2高液位传感器为1时,置位M2.3步,复位M2.2步。 6、程序段

qq_52251819的博客 1万+

UFS总体介绍及FPGA开发

通过实现UFS的主控制器、设备控制器等组件,我们可以在FPGA上进行UFS开发,并实现高速数据传输和低功耗特性的存储解决方案。物理层负责传输物理信号,数据链路层提供数据包的传输和错误检测功能,传输层处理数据包的分段、重组和重传,逻辑层管理设备和主控制器之间的命令和数据传输,文件系统层负责文件管理和数据存储。在本文中,我们将介绍UFS的总体架构和特性,并探讨如何在FPGA上进行UFS开发。这些组件的实现涉及到UFS协议的具体细节和硬件平台的特性,因此需要参考UFS协议规范和FPGA开发平台的相关文档。

PodProgram的博客 2135

浅谈C语言程序在Linux下的内存布局

浅谈C语言程序在Linux下的内存布局 ​ 在了解内存布局前,先要了解程序的虚拟地址空间以及编译模式。 ​ 所谓的虚拟空间,就是程序可以使用的虚拟地址的有效范围。虚拟地址和物理地址的映射关系由操作系统决定,相应地,虚拟地址空间的大小也由操作系统决定,但还会受到编译模式的影响。 ​ 先了解CPU,然后再了解编译模式。再来看程序在内存中的分布。 一、CPU ​ CPU是计算机的核心,决定了计算机的数据...

Cchengyoyoy的博客 853

本地通知与健康数据的隐私保护方案

随着移动健康(mHealth)应用的普及,本地通知与健康数据的结合为用户提供了更加个性化的健康管理体验。然而,这种便利性也带来了严峻的隐私保护挑战。本文旨在探讨如何在移动应用中实现本地通知功能的同时,确保用户健康数据的隐私安全。本地通知与健康数据结合的技术架构隐私保护的核心技术方案具体算法实现与数学模型实际应用案例分析本文首先介绍背景知识和核心概念,然后深入探讨隐私保护的技术方案,包括算法原理和数学模型。接着提供实际代码实现和应用场景分析,最后讨论未来发展趋势和挑战。

移动开发前沿的博客 1309

C语言程序的内存空间布局

C语言程序是编译后的二进制程序,其对目标操作系统依赖性非常强,如:Linux程序无法在Windows系统上直接运行,反之亦然,再如:64位程序无法允许在32位系统。对于C语言程序的内存存储空间的布局,还是需要了解一下的。 C语言程序主要分为:正文段,初始化数据段,非初始化数据段,栈,堆等。 正文段:CPU执行机器指令的部分,该段是只读的。 初始化数据段:简称数据段,已初始化的变量(全局,静态...

weixin_34206899的博客 204

向华为学习——解读华为战略规划SP与业务计划BP流程【附全文阅读】

该方案针对大中型企业高管及战略团队,系统拆解华为SP(4-9月中长期规划)与BP(10-12月年度执行)双轨体系,形成"战略制定-业务设计-资源配置-绩效解码"闭环。SP侧重市场趋势分析、业务优先级与资源分配,BP细化KPI、预算及行动计划。通过价值树、战略解码等工具实现战略到部门/个人的目标分解,强化跨部门协同与过程管控。配套17份华为实战资料(包括战略管理、流程优化、销售组织建设等核心方法论),助力企业建立规范的战略执行体系,实现资源优化与绩效落地。

cdfunlove的博客 768

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

C语言程序的内存布局(一)C语言程序的存储区域

第13章 C语言程序的内存布局 本章介绍C语言程序的内存布局结构,包括连接过程中目标程序各个段的组成和运行过程中各个段加载的情况。 在本章的学习中,读者应重点关注以下内容: C语言程序在内存中各个段的组成 C语言程序连接过程中的特性和常见错误 C语言程序的运行方式 13.1  C语言程序的存储区域 由C语言代码(文本文件)形成可执行程序(二进制文件),需要经过编译-汇编-连接三个阶段

mystudyblog0507的专栏 511

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

15 C语言程序的内存布局

例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。提示:以下是本篇文章正文内容,下面案例可供参考​内存是存放运行数据的硬件,硬盘中的程序执行前要先放到内存中才能被CPU去处理,CPU也被设计为多数情况下从内存读取数据和指令,处理的结果也事先存放到内存。内存是与CPU沟通的桥梁。文件是保存在硬盘中的,我们打开一个文件,这个文件从磁盘先加载(复制)到内存。这个过程需要用到一个工具——加载器。

wmjdiidjjisjb的博客 374

android 蓝牙通讯demo

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

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

C语言程序的内存布局(四)C语言程序的运行

13.4  C语言程序的运行 在嵌入式系统中,程序最终是要放置在内存中运行的,程序的几个段,最终会转化为内存中的几个区域。C语言可执行程序的内存布局如图13-5所示。   (图13-5  C语言可执行程序的内存布局 在内存中,从低地址到高地址,依次是只读段、读写段、未初始化数据段、堆段、栈段。 映像文件中将包含代码段(Code)、只读数据段(RO Data

mystudyblog0507的专栏 935
上一篇: 大小端,内对齐及函数跳转在嵌入式中的应用
下一篇: C语言中的位运算在嵌入式中的应用
wustdatamining
博客等级 码龄15年 12粉丝 81原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值