C程序内存分布及static变量

C程序内存分布及static变量

    • C语言中程序的内存分布 [🔗1](https://www.cnblogs.com/miaoxiong/p/11021827.html)[🔗2](https://blog.csdn.net/chen1083376511/article/details/54930191)
      • c/c++编译连接后二进制文件的存储
      • 动静态存储方式和存储区
        • 动态存储方式
        • 动态存储区
        • 静态存储方式
        • 静态存储区
    • static修饰[🔗](https://blog.csdn.net/stoic163/article/details/104711574)
      • static修饰的全局变量
      • static修饰的局部变量
      • static修饰的函数
      • 总结
    • 存储说明符[🔗](https://www.cnblogs.com/Natsumeno/p/14499173.html)

C语言中static类型表示“静态”或者“全局”的意思,用来修饰变量函数。经其修饰过的变量或函数作用域存储域会发生变化。

C语言中程序的内存分布 🔗1🔗2

c/c++编译连接后二进制文件的存储

  1. 代码段(text段)-- 可执行指令构成,程序在目标文件或内存中的一部分。通常只读,放置程序突发性的修改。

  2. 已初始化数据段(data段)-- 占程序虚拟地址空间一部分,包含全局变量静态变量(程序负责初始化这些变量)。 不是只读,运行时变量值可以变动。可细分为初始化只读区及初始化可读写区。

    //存储在初始化可读写区
    全局字符串 char s[] = "hello world";
    全局变量   int debug = 1;
    静态变量   static int i = 10; 
    //字符串"hello world"存储在初始化只读区  string指针存储在初始化可读写区
    常量修饰 const char* string  = "hello world";
  3. 未初始化数据段(bss段)-- 段内的数据在程序开始执行之前被内核初始化为0值,通常开始于已初始化数据段的末尾处。段内包含初始化为0的全局变量/静态变量以及源码中未显示进行初始化的变量。

    static int i;
    int j;
  4. 栈(stack) – 栈存储着自动变量以及每次函数调用时保存的信息,自顶向下增长;栈是属于线程的,每一个线程都有一个自己的栈。

  5. 堆(heap)-- 堆空间起始于bss段的末尾,并向高地址处生长。通常用作动态内存分配,通常由malloc realloc free管理,在一个进程中,堆空间被进程内所有的共享库及动态加载模块所共享。

进程运行时的典型内存布局

img

动静态存储方式和存储区

动态存储方式

==程序运行期间根据需要进行动态的分配存储空间的方式。==动态存储变量在程序执行过程中,使用它时才分配存储单元,使用完后立即释放。例如函数的形式参数函数定义时并不分配存储单元,函数调用时才分配。调用结束后立即释放。

动态存储区
  1. 堆和栈
  2. 局部自动变量
  3. 自动变量(未加static声明的局部变量)(3,4??)
  4. 函数调用时的现场保护和返回地址
  5. 动态变量(heap里由new/malloc分配的空间,声明周期到free结束)
静态存储方式

程序编译期间分配固定的存储空间的方式。

在变量定义时就分定存储单元并一直保持不变, 直至整个程序结束。全局变量,静态变量等就属于此类存储方式。

静态存储区

包括常量、常变量(const 变量)、静态变量、全局变量等。

static修饰🔗

static修饰的全局变量

在全局变量之前加上关键字static,全局变量被定义为一个全局静态变量

  • 内存中的位置:静态存储区,在整个程序运行期间都都行
  • 初始化:未经初始化的全局静态变量会被程序自动初始化未0(未初始化的自动对象的值是任意的)
  • 作用域:全局静态变量在声明它的文件外是不可见的,从定义之处开始到文件结尾
  • 用处:不会被其他文件访问修改,其他文件可以使用相同名字的变量不会发生冲突

注:static修饰全局变量时,改变了全局变量的作用域(声明它的文件之外是不可见的),不过没有改变它的存放位置,还是在静态存储区中。

static修饰的局部变量

局部变量之前加上关键字static,局部变量被定义未一个局部静态变量

  • 内存中的位置:静态存储区
  • 初始化:未经初始化的局部静态变量会被程序自动初始化为0
  • 作用域:仍未局部作用域,在定义它的函数或语句块从定义开始到函数或语句块结束,作用域结束

注: 特点是用static修饰局部变量改变了其存储位置,从栈中变到了静态存储区,虽然作用域仍然为局部作用域,但是在离开作用域后没有被销毁,仍然存留在内存中,直到程序结束,当该函数被多次调用时可以再次访问,下次函数被调用时,可以访问最近一次被修改后的值。应该是这样哈。

static修饰的函数

在函数返回类型前加static,函数被定义为静态函数。函数的定义和声明默认是extern的静态函数只在声明其的文件中可见,不能被其他文件所用。因此文件内部调用的函数,可以定义为static的,如果有头文件也无需在头文件声明。有h文件和c文件的模块,开放给外部的接口函数才需要在h文件中声明。

  • 用处:其他文件中可以定义相同名字的函数,不会发生冲突,静态函数不能被其他文件所用。

总结

  1. 隐藏
  2. 保持变量内容持久,存储在静态数据区的变量会在程序刚开始运行时完成初始化,也是唯一一次初始化。共有两种变量存在静态存储区:全局变量和静态变量。不过静态变量可以控制可见范围。不过对于对局部变量添加static的修饰则就是为了让他保持仅是局部作用域但是局部作用域出了之后变量不被销毁>。
  3. 默认初始化为0,全局变量也具备这一属性。

存储说明符🔗

四种存储类别:auto register extern static

两种存储期:自动存储期(auto register) 静态存储期(extern static

  • auto:自动存储期变量在进入声明该变量的程序块时被建立,它在该程序块活动时存在,退出该程序块时撤销(消失)。

  • register:存储在CPU内部,而不是存在内存【需要内存寻址访问】,可以提高效率。该变量作为一个寄存器变量,让该变量的访问速度达到最快。循环中的变量需要被频繁使用时, 可以声明为register类型。

    限制:无法使用&获取变量地址;必须是一个单个值,长度应小于等于整形长度;局部静态变量不能定义为寄存器变量。

  • extern:声明一个全局变量/外部变量, 作用在整个程序工程。定义和声明分开且定义只能一次,声明可以多次。

static与auto

  • 变量在静态存储区被分配存储单元, 在程序运营期间都不释放。 但是auto 自动变量/局部变量, 在动态存储区空间, 函数调用后结束后即释放。
  • 只在编译时赋值一次, 【不赋值则默认为0】。 以后调用函数时不需要再次赋值,而是使用上次函数调用结束的值。 但是,为auto自动变量赋值, 不是在编译时进行赋值,而是在函数调用时进行赋值, 每调用一次,就重新赋一次初值。
  • 不给static变量赋值,默认为0,不给auto变量复制,值不确定。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/681276.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

proteus使用问题

1、无法和视频里面一样新建工程 2、实验效果和视频不也一样 自己的电路图(灯不亮):

【Spring】GoF 之代理模式

一、代理模式 在 Java 程序中的代理模式的作用: 当一个对象需要受到保护的时候,可以考虑使用代理对象去完成某个行为 需要给某个对象的功能进行功能增强的时候,可以考虑找一个代理进行增强 A 对象无法和 B 对象直接交互时,也可以…

21_Scala集合_可变数组ArrayBuffer

文章目录 ArrayBuffer1.创建可变数组ArrayBuffer2.增加数据3.删除数据4.修改数据5.查询数据Appendix ArrayBuffer ArrayBuffer可变数组–感觉优点类似于Java的ArrayList 1.创建可变数组ArrayBuffer –请注意下面的mutable import scala.collection.mutable.ArrayBuffer //m…

Audition处理音频文件背景音(保留人声)

音频文件背景音可以使用Adobe Audition进行处理,Adobe Audition的下载与安装见之前博客: Adobe Audition 2024 下载与安装-CSDN博客https://blog.csdn.net/xiaoxian666/article/details/138612837?spm1001.2014.3001.5502 一、选中一段不含人声的背景…

ESD静电问题 | PCB布局布线对防护效果的影响

【转自微信公众号:韬略科技EMC】

C语言例题38、有n个人围成一圈,顺序排号。从第一个人开始报数(从1到3报数),凡报到3的人退出圈子,最后留下来的是原来第几号人员?

#include <stdio.h> #define MAX_CALLER 3void main() {int j 0;int p_total;//人数int p_caller 0;//每3人循环计数&#xff1a;1,2,3int p_exit 0; //退出游戏的人数int people[255] {0};//参与游戏人员名单printf("请输入参与游戏人数&#xff1a;");s…

通过编写dockerfile部署python项目

docker命令总览 docker通过dockerfile构建镜像常用命令 # 创建镜像&#xff08;进入dockerfile所在的路径&#xff09; docker build -t my_image:1.0 .# 查看镜像 docker images# 创建容器 docker run -dit --restartalways -p 9700:9700 --name my_container my_image:1.0 #…

一款开源的原神工具箱,专为现代化 Windows 平台设计,旨在改善桌面端玩家的游戏体验

Snap.Hutao 胡桃工具箱是一款以 MIT 协议开源的原神工具箱&#xff0c;专为现代化 Windows 平台设计&#xff0c;旨在改善桌面端玩家的游戏体验。通过将既有的官方资源与开发团队设计的全新功能相结合&#xff0c;提供了一套完整且实用的工具集&#xff0c;且无需依赖任何移动设…

24 | MySQL是怎么保证主备一致的?

MySQL 主备的基本原理 内部流程 备库 B 跟主库 A 之间维持了一个长连接。主库 A 内部有一个线程,专门用于服务备库 B 的这个长连接。一个事务日志同步的完整过程是这样的: 在备库 B 上通过 change master 命令,设置主库 A 的 IP、端口、用户名、密码,以及要从哪个位置开始…

VLM与基础分割模型的联合使用

最近做的项目里有涉及大模型&#xff0c;里面有一部分的功能是&#xff1a; 将图片输入VLM(视觉语言模型&#xff0c;我使用的是llava)&#xff0c;询问图中最显著的物体&#xff0c;将其给出的答案作为基础分割模型&#xff08;我使用的是Grounded-SAM&#xff09;的text prom…

TMS320F280049 EQEP模块--Interrupt(6)

功能框图 12个中断源&#xff1a;PCE, PHE, QDC, WTO, PCU, PCO, PCR, PCM, SEL, IEL, UTO, QMAE 在QEINT中使能对应bit后&#xff0c;当发生该事件时会使QFLAG.INT置位且中断传递出去。 查看哪个事件触发的中断&#xff0c;可查看QFLAG寄存器。 清中断可使用QCLR寄存器。 …

算法学习:递归

&#x1f525; 个人主页&#xff1a;空白诗 文章目录 一、引言二、什么是递归&#xff1f;三、两大基本要素&#x1f3c1; 基线条件&#xff08;Base Case&#xff09;&#x1f501; 递归条件&#xff08;Recursive Case&#xff09;&#x1f4c3; 代码示例&#xff1a;计算斐波…