存储类别、链接与内存管理(二)
0、前言概要
本篇来自于我的另外一篇博客存储类别、链接与内存管理(一)的续篇,主要分析了C语言中的不同存储类别、关键字以及使用的注意事项

1、自动变量
(1)属性
自动存储期、块作用域、无连接
(2)关键字[存储类别声明符]:auto
(3)使用例子
int loop(int n){ auto int m;}
(4)关键解析
- auto关键字在C++代码中完全不同,如果写C和C++兼容的语言,最好不要使用auto关键字
- 由于块内使用的变量大都是auto修饰的自动变量,所以在中的程序中auto关键字使用的非常少,除非你想强调这是一个自动变量
- 块作用域和无链接属性意味着只有在变量定义的块中才能“直接”使用变量名来访问该变量(当然排除通过指针的情况,这种属于间接)
- 变量具有自动存储期意味着,程序在进入该变量声明的所在块时存在,退出程序的时候变量消失
- 当变量消失的时候,该变量原来占有的内存位置现在可做他用
- 自动变量不会自己初始化,除非显示初始化它。另外可以用非常量表达式初始化自动变量,前提是所用的变量之前有定义过
int main(void)
{int ruth = 1;//显式初始化int rance = 5 * ruth;//使用了之前初始化过的变量
}
2、寄存器变量
(1)属性
自动存储期、块作用域、无链接
(2)关键字[存储类别声明符]:register
(3)使用例子
int main()
{register int quick;
}
(4)关键解析
- 寄存器变量存储在CPU的寄存器中,寄存器的数据传递速度是极快的,但是通常寄存器的空间不会太大
- 与普通变量相比,访问和处理寄存器变量的速度更快
- 由于寄存器变量存储在寄存器而非内存当中,所以无法获取寄存器变量的地址(这一点可以用&检验一下)
- 该关键字更像是请求而不是直接命令,编译器必须根据寄存器或最快可用的内存的数量衡量你的要求(或是忽略你的要求,这种情况下寄存器变量就会转化为自动变量)。即使是这样,也依旧不能对被修饰了register的变量取地址
- 可声明为register的数据类型有限,例如处理器中的寄存器可能就没有足够大的空间来存储double类型的值
3、静态外部链接变量
(1)属性
静态存储期、文件作用域、外部链接
(2)关键字[存储类别说明书]:extern
(3)使用例子
//第一个.c文件内容
int a = 100;
//第二个.c文件内容
#include <stdio.h>
int main()
{extern a;printf("%d", a);return 0;
}
(4)关键解析
- 把一个变量的定义放在所有函数(包括mian)的外面,那么该变量就是外部变量
- 把变量的定义性声明放在所有函数的外面边创建了外部变量,此时如果为了强调函数使用了外部变量可以在函数内部使用关键字extern再次声明;但是如果是在别的.c文件里声明的外部变量,就必须使用extern再次声明
//第一个.c文件
char Coal = 100;
char arr[10] = { 'a', 'b', 'c' };
//第二个.c文件
int Errupt;//在本文件的外部变量
double Up[100];//在本文件的外部变量数组extern char Coal;//在其他文件的外部变量
extern char arr[];//在其他文件的外部变量数组int main()
{extern int Errupt;//可写可不写extern double Up[];//可写可不写//使用Errupt和Up的代码//使用Coal和arr的代码return 0;
}
- 在外部变量数组中,可以看到不需要指明数组的大小,因为第一次已经提供了数组大小的信息
- 由于外部变量本身具有文件作用域所以在main里面的extern整条语句完全可以省略,但是如果只是省略extern(比如剩下int Errupt)就会重新定义一个名未Errupt的自动变量,这个自动变量Errupt和外部变量Errupt是不同的
- 静态外部变量可以被显示初始化,也可以不显示初始化(默认初始化未0,数组也一样),但是只能使用常量表达式进行初始化
int i = 10;//没问题
int j = 3 + 20;//没问题
int x = sizeof(int);//没问题,只要不是变长数组sizeof可以视为常量表达式
int y = 10 * i;//不允许
int main()
{//某些代码
}
- extern关键字只是一种引用式声明,不是定义式声明,因此不要用关键字extern创建一个外部变量的定义,它只能用来引用现有的外部变量定义
- 外部变量只能初始化一次,并且必须在定义该变量时进行
//第一个.c文件
int a = 100;
//第二个.c文件
int main()
{extern int a = 200;//这是不被允许的!因为在另外一个文件里已经初始化为100了a = 200;//但是如果上面只写extern int a;使用赋值就可以,赋值不是初始化
}
4、静态内部链接变量
(1)属性
静态存储期、文件作用域、内部链接
(2)关键字[存储类别关键字]:static
(3)使用例子
static int svil = 1;int main(){ //某些代码
(4)关键解析
- 在内部链接的静态变量只能在本文件内部使用
- 另外也可以使用extern在函数的内部声明存在这个外部变量(注意不会改变链接属性!)
int a = 1;//具有外部链接属性
static int b = 2;//具有内部链接属性
int main()
{printf("%d %d\n", a, b);{extern int a;//提醒a是外部变量,但是依旧是外部连接属性extern int b;//提醒外部变量,但是依旧是内部连接属性printf("%d %d", a, b);}return 0;
}
5、静态无链接变量
(1)属性
静态存储期、块作用域、无链接
(2)关键字[存储类别说明书]:static
(3)使用例子
#include <stdio.h>
void trystat(void)
{int fade = 1;static int stay = 1;printf("fade = %d and stay = %d\n", fade++, stay++);
}
int main()
{int count;static int number;for (count = 1; count <= 3; count++){printf("Here comes iteration %d:\n", count);trystat(); }printf("%d\n", number);return 0;
}
(4)关键解析
- 静态的意思是该变量在内存中原地不动(计算机会记录它的值),并不是说它的值不变,它不像自动变量一样在一定范围使用完后就被销毁
- 每次调用函数trystat后fade会被重新初始化为1,stay只在只会在编译trystat函数时被初始化一次
- 第一条声明fade确实是trystat函数的一部分,每次调用该函数都会执行这条声明;第二条声明stay实际上不是trystat函数的一部分,如果逐语句调试就会发现这条指令貌似被跳过了?这是因为静态变量和外部变量在程序被载入的时候就已经执行完毕。第二条声明语句放进函数中是为了告诉编译器只有在trystat函数才能看到该变量
- 如果未显式初始化静态变量,就会被自动初始化为0。例如本例中的number在打印的时候并未报错,甚至还自动给了number一个0的值
6、参考来源
来自书籍《C primer puls》第12章的“存储类别、链接和内存管理”章节
相关文章:
存储类别、链接与内存管理(二)
0、前言概要 本篇来自于我的另外一篇博客存储类别、链接与内存管理(一)的续篇,主要分析了C语言中的不同存储类别、关键字以及使用的注意事项 1、自动变量 (1)属性 自动存储期、块作用域、无连接 (2&a…...
JavaScript 入门教程||javascript 简介||JavaScript 用法
javascript 简介JavaScript 是互联网上最流行的脚本语言,这门语言可用于 HTML 和 web,更可广泛用于服务器、PC、笔记本电脑、平板电脑和智能手机等设备。JavaScript 是脚本语言JavaScript 是一种轻量级的编程语言。JavaScript 是可插入 HTML 页面的编程代…...
新闻稿写作指南
当你想要传达一则新闻,写一份新闻稿是非常必要的。新闻稿的目的是让读者了解某个事件或信息,以及提供与之相关的背景信息和重要细节。以下是新闻稿的写作指南,帮助你写出一份清晰、简洁、有价值的新闻稿。1、选择一个有新闻价值的主题你的新闻…...
一文详解Redis持久化的两种方案
一文详解Redis持久化的两种方案1.RDB持久化2.RDB持久化原理3.AOF持久化4.RDB VS AOF1.RDB持久化 RDB全称Redis Database Backup file(Redis数据备份文件),也被叫做Redis数据快照。简单来说就是把内存中的所有数据都记录到磁盘中。当Redis实例故障重启后,…...
第六章 - 数据过滤where(where与and和or的组合用法)
第六章 - 数据过滤(where的用法)基本用法where的条件限制符等于号不等号! 或者<>小于<大于>小于等于<大于等于>between 的用法空值和非空值组合条件 and组合条件 orand 和 or 的计算次序in 和 not in基本用法 在查询语句中࿰…...
Oracle 定时任务例子
背景: 创建一个Oracle的定时任务,每天或指定时间 -----定义存储过程 create or replace procedure AAA_BBB as begin insert into AAA select * from BBB; commit; end; ----------------创建定时任务 declare xjobid number; begin DBMS_JOB.SUBM…...
Android常用9种自动化测试框架对比,Appium有哪些优势?
随着移动终端的普及,手机应用越来越多,也越来越重要。 App的回归测试用例数量也越来越多,全量回归也越来越消耗时间。移动 APP自动化测试 的难点移动 APP的UI自动化测试长久以来一直是一个难点,难点在于UI的”变”, 变化导致自动化…...
在vue2使用百度脑图的kityminder-core进行二次开发思维导图,给节点绑定数据后添加新的图标
需求说明:在给某个节点绑定文件数据后,用户并不能一眼看出哪个节点上绑定了数据,因此需要在绑定文件数据后给节点上加一个图标用于标识。 添加图标 1、在kityminder-core/src/module/file.js文件中添加代码 (file.js文件如何添加…...
FPGA时序约束与分析 --- 时序约束概述
本系列参考文献 — FPGA时序与约束分析-吴厚航 FPGA从综合到实现需要的过程如下:synth_design -> opt_design -> place-design -> phys_opt_design -> route_design 1、时序约束的理解 2、时序约束的基本路径 3、时序约束的步骤 4、时序约束的主要方法…...
2022——寒假总结
文章目录背景报名摸索结果总结背景 大一上学期,刚上大学没有尽快适应,什么都没有学到。 因为疫情,所以平时的测试以及期末都是线上进行的,就没怎么认真学,网课直接划水。 我的生活与学习很不平衡,还热衷于参…...
C++11 Lambda表达式
文章首发公众号:iDoitnow 为什么引入Lambda Lambda表达式是一个可以内联在我们代码中的函数,我们可以将他传递给另外一个函数。在没有引入Lambda表达式之前,当我们遇到需要对多个数据,按照同一规则进行操作的时候,创建…...
冰湖灾害遥感监测评价与模拟分析
查看原文>>>mp.weixin.qq.com/s?__bizMzAxNzcxMzc5MQ&mid2247582638&idx1&sna22a1697b16a5edc2b74cb1ccf011689&chksm9be29cbeac9515a8227460103ae1b9f280af688eab0ce5a43448f9fa7c9cab820c389fcdc031&token10630879&langzh_CN#rd【专家简介…...
Highcharts.Chart
Highcharts 是一个使用javascript 脚本来生成图表的工具,和jfreechart 作用类似,都用来生成各种图表,并支持图片的导出和打印。 从官网 www.highcharts.com 上下载的压缩表中的example中有各种图表的例子。 要编写生成图表的例子建议从 文…...
遍历map的几种方法
#先往map加入几个数据 Map<Integer,String> mapnew HashMap<>(); map.put(1,"美好的周一"); map.put(2,"美好的周二"); map.put(3,"美好的周三"); 1 2 3 4 方法一:普通的foreach循环,…...
RocketMQ源码分析之Broker概述与同步消息发送原理与高可用设计及思考
1、Broker概述 Broker 在 RocketMQ 架构中的角色,就是存储消息,核心任务就是持久化消息,生产者发送消息给 Broker,消费者从 Broker 消费消息,其物理部署架构图如下: 备注:以上摘录自官方 RocketMQ 设计文档…...
K8s常见面试题总结
部分内容来自:k8s面试题大全(持续更新中) 目录 k8s常考面试题 1.1.什么是k8s? 1.2.简述Docker和Kubernetes的关系 1.3.k8s的组件有哪些,作用分别是什么? 1.4.简述kubelet的功能和作用 1.5.简述pod是…...
OpenFeign 自定义解码器Decoder 失效
问题描述 项目上开发了OpenFeign的自定义解码器,用来统一处理返回结果。 开发完后测试已经生效了,过两天后,这块代码没有变动的情况下,发现请求结果突然又不走自定义的解码器了。 代码如下 解码器 BaseResponseFeignDecoder …...
c++练习题8
1.在do-while循环中,循环由do开始,用while结束;必须注意的是:在while表达式后面的 不能丢,它表示do-while语句的结束。 A)0 B)1 C);…...
Python循环语句代码详解:while、for、break
目录 1 while循环 1 while循环 循环语句是程序设计中常用的语句之一。任何编程语言都有while循环,Python也不例外。while循环的格式如下所示。 while(表达式): … else: … while循环的执行过程:当循环表达式为真时,依次执行whi…...
vue父子组件传值不能实时更新
最近做项目,遇到个大坑,这会爬出来了,写个总结,避免下次掉坑。 vue父子组件传值不能实时更新问题,父组件将值传给了子组件,但子组件显示的值还是原来的初始值,并没有实时更新,为什么…...
MongoDB学习和应用(高效的非关系型数据库)
一丶 MongoDB简介 对于社交类软件的功能,我们需要对它的功能特点进行分析: 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具: mysql:关系型数据库&am…...
《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)
CSI-2 协议详细解析 (一) 1. CSI-2层定义(CSI-2 Layer Definitions) 分层结构 :CSI-2协议分为6层: 物理层(PHY Layer) : 定义电气特性、时钟机制和传输介质(导线&#…...
Leetcode 3577. Count the Number of Computer Unlocking Permutations
Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接:3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯,要想要能够将所有的电脑解锁&#x…...
基于数字孪生的水厂可视化平台建设:架构与实践
分享大纲: 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年,数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段,基于数字孪生的水厂可视化平台的…...
高等数学(下)题型笔记(八)空间解析几何与向量代数
目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...
unix/linux,sudo,其发展历程详细时间线、由来、历史背景
sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...
涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战
“🤖手搓TuyaAI语音指令 😍秒变表情包大师,让萌系Otto机器人🔥玩出智能新花样!开整!” 🤖 Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制(TuyaAI…...
算法:模拟
1.替换所有的问号 1576. 替换所有的问号 - 力扣(LeetCode) 遍历字符串:通过外层循环逐一检查每个字符。遇到 ? 时处理: 内层循环遍历小写字母(a 到 z)。对每个字母检查是否满足: 与…...
七、数据库的完整性
七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分: 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...
