编程语言|C语言——C语言变量的存储方式

前言

变量是程序中数据的存储空间的抽象。变量的存储方式可分为静态存储和动态存储两种。

静态存储变量通常是在程序编译时就分配一定的存储空间并一直保持不变,直至整个程序结束。在上一部分中介绍的全局变量的存储方式即属于此类存储方式。

动态存储变量是在程序执行过程中使用它时才分配存储单元,使用完毕立即释放。典型的例子是函数的形参。在函数定义时并不给形参分配存储单元,只是在函数被调用时,才予以分配,调用函数完毕立即释放。如果一个函数被多次调用,则反复地分配、释放形参变量的存储单元。

从以上分析可知,静态存储变量是一直存在的,而动态存储变量则时而存在时而消失。因此,这种由于变量存储方式不同而产生的特性称为变量的生存期,生存期表示了变量存在的时间。

生存期和作用域是从时间和空间这两个不同的角度来描述变量的特性。这两者既有联系,又有区别。一个变量的存储方式究竟属于哪一种存储方式,并不能仅仅从作用域来判断,还应有明确的存储模型说明。

变量的存储模型由作用域、链接点及存储期三大属性来描述。其中,存储期描述的是变量在内存中的生存时间。存储模型也经常被表达为存储类,共有以下5种存储模型。

一、自动auto

变量的声明语法为

<存储类型> 数据类型 变量名

auto为存储类说明符,可以说明一个变量为自动变量。该类具有动态存储期、代码块的作用域和空链接。如果变量没有初始化,它的值是不确定的。

代码块或者函数头部定义的变量,可使用存储类修饰符auto来明确标识属于自动存储类型。若没有使用auto修饰,也属于自动存储类型。

例如:

{int i,j,k;charc;
)

等价于:

{auto int i,j,k;auto charc;
}

自动变量具有以下特点:

  • 自动变量的作用域仅限于定义该变量的模块内。在函数中定义的自动变量,只在该函数内有效。在复合语句中定义的自动变量,只在该复合语句中有效。
  • 自动变量属于动态存储方式,只有在定义该变量的函数被调用时才给它分配存储单元,开始它的生存期。函数调用结束,释放存储单元,结束生存期。因此函数调用结束之后,自动变量的值不能保留。在复合语句中定义的自动变量,在退出复合语句后也不能再使用,否则将引起错误。
  • 由于自动变量的作用域和生存期都局限于定义它的模块内(函数或复合语句内),因此不同的模块中允许使用同名的变量而不会混淆。即使在函数内定义的自动变量也可与该函数内部的复合语句中定义的自动变量同名,但读者应尽量避免使用这种方式。

例如:

int loop(int n)
{int m;m=2;{int i,m;//m,i的作用域m=20;for(i=m;i<n;i++)printf(……);}//m作用域,i消失return m;
}

二、寄存器

在一个代码块内(或在一个函数头部作为参量)使用修饰符register声明的变量属于寄存器存储类。register修饰符暗示编译程序相应的变量将被频繁使用,如果可能的话,应将其保存在CPU的寄存器中,从而加快其存取速度。该类与自动存储类相似,具有自动存储期、代码块作用域和空链接。如果没有被初始化,它的值也是不确定的。

使用register修饰符有几点限制。

  • register变量必须是能被CPU寄存器所接受的类型,这通常意味着register变量必须是一个单个的值,并且其长度应小于或等于整型的长度(int char *p)。这与处理器的类型有关。
  • 声明为register仅仅是一个请求,而非命令,因此变量仍然可能是普通的自动变量,没有放在寄存器中。
  • 由于变量有可能存储在寄存器中,因此不能用取地址运算符“&”获取register变量的地址。如果有这样的写法,编译器会报错。
  • 只有局部变量和形参可以作为register变量,全局变量不行。
  • 实际上有些系统并不把register变量存放在寄存器中,而优化的编译系统则可以自动识别使用频繁的变量而把它们放在寄存器中。

三、静态和空链接

静态变量的类型说明符:static。在一个代码块内使用存储类修饰符static声明的局部变量属于静态空链接存储类。该类具有静态存储时期、代码块作用域和空链接。

静态变量的存储空间是在编译完成后就分配了,并且在程序运行的全部过程中都不会撤销。这里要区别的是,属于静态存储方式的变量不一定就是静态变量。

例如外部变量虽属于静态存储方式,但不一定是静态变量,必须由static加以定义后才能称为静态外部变量,或称静态全局变量。

对比图

静态变量可分为静态局部变量和静态全局变量。静态局部变量属于静态存储方式,它具有以下特点。

  • 静态局部变量在函数内定义,它的生存期为整个程序执行期间,但是其作用域仍与自动变量相同,只能在定义该变量的函数内使用该变量。退出该函数后,尽管该变量还继续存在,但不能使用它。
  • 可以对构造类静态局部量赋初值、例如数组。若未赋初值,则由系统自动初始化为0。
  • 基本数据类型的静态局部变量若在说明时未赋初值,则系统自动赋予0。而对自动变量不赋初值。值就是不确定的,根据静态局部变量的特点,可以看出它是一种生存期为整个程序运行期的变量。虽然离开定义它的函数后不能使用、但如再次调用定义它的函数时,它又可以继续使用,并且保留了上次被调用后的值,

因此、当多次调用一个函数且要求在调用之前保留某些变量的值时,可以考虑采用静态局部变量。虽然用全局变量也可以达到上述目的,但全局变量有时会造成意外的副作用、因此仍以采用静态局部变量为宜。

四、静态和外部链接

未使用static修饰的全局变量属于静态、外部链接存储类。具有静态存储时期、文件作用域和外部链接。仅在偏译时初始化一次。如未明确初始化,它的字节也被设定为0。在使用外部变量的函数中使用extern关键字来再次声明。如果是在其他文件中定义的,则必须使用extern。

五、静态和内部链接

全局变量在关键字之前再冠以static就构成了静态的全局变量,属于静态、内部链接存储类。与静态、外部链接存储类不同的是、具有内部链接,使得仅能被与它在同一个文件的函数使用。这样的变量也是仅在编译时初始化一次。如未明确初始化,它的字节被设定为0。

这两者的区别在于非静态全局变量的作用域是整个源程序,但当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的;而静态全局变量则限制了其作用域,即只在定义该变量的源文件内有效、在同一源程序的其他源文件中不能使用。

由于静态全局变量的作用域局限于一个源文件内,只能被该源文件内的函数使用,因此可以避免在其他源文件中引起错误。

静态全局变量及非静态全局变量的区别示意图。

从以上分析可以看出,把局部变量改变为静态变量后改变了它的存储方式,即改变了它的生存期。把全局变量改变为静态变量后改变了它的作用域,限制了它的使用范围。因此static这个说明将在不同的地方所起的作用是不同的。
例如:源文件a.c

	int a=10;/全局变量,静态外部链接static int b=20:/静态全局变量,静态内部链接intf(){int m=30;return m;}

源文件b.c

	#include<stdio.h>/*使用extern关键字,声明外部变量*/extern int b;extern int a:int main(){printf("a=%d\n",a);printf("b=%d\n",b);return 0:}

编译程序,出现以下错误:

error:In function*main':
static _b.c:(. text+0x22):undefined reference to'b'
collect2:Id returned 1 exit status

分析:本例说明了,普通全局变量,是外部链接,可以被其他文件引用。有static关键字修饰的静态全局变量,是内部链接,限制了变量只在当前文件使用。

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

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

相关文章

C++自主点餐系统

一、 题目 设计一个自助点餐系统&#xff0c;方便顾客自己点餐&#xff0c;并提供对餐厅销售情况的统计和管理功能。 二、 业务流程图 三、 系统功能结构图 四、 类的设计 五、 程序代码与说明 头文件1. SystemMap.h #pragma once #ifndef SYSTEMMAP #define SYSTEMMAP #in…

集体出走的Stability AI 发布全新代码大模型,3B以下性能最优,超越Code Llama和DeepSeek-Coder

Stability AI又有新动作&#xff01;程序员又有危机了&#xff1f; 3月26日&#xff0c;Stability AI推出了先进的代码语言模型Stable Code Instruct 3B&#xff0c;该模型是在Stable Code 3B的基础上进行指令调优的Code LM。 Stability AI 表示&#xff0c;Stable Code Instru…

3款免费甘特图制作工具的比较和选择指南

GanntProject GanttProject https://www.ganttproject.biz/ 是一款项目管理和调度应用&#xff0c;适用于 Windows、macOS 和 Linux。它易于使用&#xff0c;无需任何设置&#xff0c;适用于个人用户和小型团队。该应用提供任务层次结构和依存关系、里程碑、基准行、Gantt 图表…

WordPress Git主题 响应式CMS主题模板

分享的是新版本&#xff0c;旧版本少了很多功能&#xff0c;尤其在新版支持自动更新后&#xff0c;该主题可以用来搭建个人博客&#xff0c;素材下载网站&#xff0c;图片站等 主题特点 兼容 IE9、谷歌 Chrome 、火狐 Firefox 等主流浏览器 扁平化的设计加响应式布局&#x…

BioXcell InVivoPlus anti-mouse Ly6G及部分参考文献

BioXcell InVivoPlus anti-mouse Ly6G 1A8单克隆抗体与小鼠Ly6G反应。Ly6G分子量为21-25kDa&#xff0c;是GPI锚定的细胞表面蛋白Ly-6超家族的成员&#xff0c;在细胞信号传导和细胞粘附中发挥作用。Ly6G在发育过程中由骨髓谱系中的细胞&#xff08;包括单核细胞、巨噬细胞、粒…

android 集合总结

1 集合分类&#xff0c; collection和map两大类,Iterator接口是提供遍历任何Collection的接口&#xff0c;不是map 2 集合类的底层实现 hashset基于hashmap实现&#xff08;只不过HashSet里面的HashMap所有的value都是同一个Object而已&#xff09; treeset由红黑树实现 …

什么是根据人类反馈的强化学习Reinforcement Learning with Human Feedback(RLHF)?

基于人类反馈的强化学习&#xff08;Reinforcement learning with human feedback&#xff09;是近年来越来越受欢迎的一种前沿技术&#xff0c;用于提高大型语言模型的性能。这是种使用人类反馈训练这些模型的有效方法&#xff0c;而该方法的输入组件与搜索评估也有诸多相似之…

[Flutter]环境判断

方式一&#xff08;推荐&#xff09; 常量kReleaseMode&#xff0c;它会根据你的应用是以什么模式编译的来获取值。bool.fromEnvironment会从Dart编译时的环境变量中获取值。对于dart.vm.product这个特定的环境变量&#xff0c;它是由Dart VM设置的&#xff0c;用来标明当前是…

【Android 源码】Android源码下载指南

文章目录 前言安装Repo初始化Repo选择分支没有梯子替换为清华源 有梯子 下载源码下载开始参考 前言 这是关于Android源码下载的过程记录。 环境&#xff1a;Windows上通过VMware安装的Ubuntu系统 安装Repo 创建Repo文件目录 mkdir ~/bin PATH~/bin:$PATH下载Repo工具&#…

回文子串 每日温度 接雨水

647. 回文子串 力扣题目链接 如果s【i】和s【j】相同 dp【i1】【j-1】也是回文串的话 &#xff08;等于true&#xff09; 那么dp【i】【j】也是回文串 true 定义一个bool二维数组 遍历顺序是从下到上 从左到右 因为dp【i】【j】是通过dp【i1】【j-1】推出来的 i从最后一…

【漏洞复现】用友U8Cloud nc.bs.sm.login2.RegisterServlet SQL注入漏洞

0x01 产品简介 用友U8 Cloud是用友推出的新一代云ERP,主要聚焦成长型、创新型企业,提供企业级云ERP整体解决方案 0x02 漏洞概述 用友U8Cloud nc.bs.sm.login2.RegisterServlet接口处存在SQL注入漏洞,未授权的攻击者可通过此漏洞获取数据库权限,从而盗取用户数据,造成用…

OpenGL 实现“人像背景虚化“效果

手机上的人像模式,也被人们称作“背景虚化”或 ”双摄虚化“ 模式,也称为 Bokeh 模式,能够在保持画面中指定的人或物体清晰的同时,将其他的背景模糊掉。突出画面的主体部分,主观上美感更强烈。 人像模式的一般实现原理是,利用双摄系统获取景深信息,并通过深度传感器和图…

WorkPlus智能AI助理:定制化部署,拓展企业协作新境界

近年来&#xff0c;随着人工智能技术不断发展&#xff0c;智能助理在企业管理中发挥着日益重要的作用。其中&#xff0c;WorkPlus智能AI助理作为一款支持私有化部署的新一代智能助理软件&#xff0c;为企业内部协作场景带来了全新的可能性。通过结合企业自身的行业知识和应用场…

英伟达推出“地表最强AI芯片”

B站&#xff1a;啥都会一点的研究生公众号&#xff1a;啥都会一点的研究生 近期AI相关资讯&#xff0c;一起看看吧~ Neuralink首位脑芯片患者用意念下棋 埃隆-马斯克&#xff08;Elon Musk&#xff09;的脑芯片初创公司 Neuralink 展示了其首位脑芯片患者仅用意念下棋的情景…

VMware vSAN OSA存储策略 - 基于虚拟机的分布式对象存储

简介 博客&#xff1a;https://songxwn.com/ 存储策略 (Storage Policy) 是管理员定义的一组规则&#xff0c;这组规则定义了数据对象在 vSAN 存储上是如何保存的&#xff0c;存储策略定义了数据存储的可靠性、访问性能等特性。vSAN 提供了基于存储策略的存储管理 SPBM (Stor…

基于java实现的高校二手交易平台

开发语言&#xff1a;Java 框架&#xff1a;ssm 技术&#xff1a;JSP JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09; 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclip…

无服务数据库是未来的趋势吗?

无服务数据库是未来的趋势吗&#xff1f; 无服务器数据库是未来的趋势吗&#xff1f;无服务器数据库与传统云数据库有何不同&#xff1f; Amazon Aurora Serverless&#xff08;如下图所示&#xff09;是 Amazon Aurora 的一种配置方式&#xff0c;可以按需自动扩展。 Aurora…

针对ETC系统的OBE-SAM模块设计方案

ETC系统组成及工作原理 ETC系统由前端系统和后台数据库系统组成&#xff0c;总体的架构如下图所示&#xff1a; 前端系统包含安装在汽车挡风玻璃上的车载单元&#xff08;On Board Unit&#xff0c;简称OBU&#xff09;、路侧单元&#xff08;Roadside Unit&#xff0c;简称RS…

深入解析Spring MVC: 原理、流程【面试版】

什么是SpringMV? 1.是一个基于MVC的web框架&#xff1b; 2.是spring的一个模块&#xff0c;是spring的子容器&#xff0c;子容器可以拿父容器的东西&#xff0c;但是反过来不可&#xff1b; 2.SpringMVC的前端控制器是DispatcherServlet&#xff0c;用于分发请求。使开发变…

python--切片

1.切片&#xff1a; 切片是编程语言为有序序列&#xff08;sequence&#xff09;准备的&#xff0c;用来切割或者截取某个片段 一个完整的切片是包含三个参数和两个冒号" : " ,用于分隔三个参数(start_index、end_index、step)。当只有一个“:”时&#xff0c;默认第…