《C和指针》笔记12: 存储类型(自动变量、静态变量和寄存器变量)

文章目录

  • 1. 自动变量(auto)
    • 1.1 自动变量的初始化
  • 2. 静态变量(static)
    • 2.1 静态变量的初始化
  • 3. 寄存器变量(register)

1. 自动变量(auto)

代码块内部声明的变量的缺省存储类型是自动的(automatic),也就是说它存储于堆栈中,称为自动(auto)变量。关键字auto就是用于修饰这种存储类型的,但它极少使用,因为代码块中的变量在缺省情况下就是自动变量。

在程序执行到声明自动变量的代码块时,自动变量才被创建,当程序的执行流离开该代码块时,这些自动变量便自行销毁。如果该代码块被数次执行,例如一个函数被反复调用,这些自动变量每次都将重新创建。在代码块再次执行时,这些自动变量在堆栈中所占据的内存位置有可能和原先的位置相同,也可能不同。即使它们所占据的位置相同,你也不能保证这块内存同时不会有其他的用途。

因此,我们可以说自动变量在代码块执行完毕后就消失。当代码块再次执行时,它们的值一般并不是上次执行时的值

举一个例子(这个例子来自于Linux C编程一站式学习-全局变量、局部变量和作用域)

#include <stdio.h>
void foo(void)
{int i;printf("%d\n", i);i = 777; }int main(void) 
{ 	foo(); 	foo(); 	return 0; 
}

打印结果:
在这里插入图片描述
第二次调用打印的i值正是第一次调用末尾赋给i的值777?

改写一下,中间加一个打印’hello’的语句。

int main(void)
{foo();printf("hello\n");foo();return 0;
}

结果是
在这里插入图片描述
第二次调用foo打印的i值又不是777了而是0,“局部变量的存储空间在每次函数调用时分配,在函数返回时释放”

所以每一次函数的调用都是重新为自动变量分配内存的。

1.1 自动变量的初始化

自动变量的初始化需要更多的开销,因为当程序链接时还无法判断自动变量的存储位置。事实上,函数的局部变量在函数的每次调用中可能占据不同的位置。基于这个理由,自动变量没有缺省的初始值,而显式的初始化将在代码块的起始处插入一条隐式的赋值语句。这导致了:

  • 自动变量的初始化较之赋值语句效率并无提高,除了声明为const的变量之外,在声明变量的同时进行初始化和先声明后赋值只有风格之差,并无效率之别;
  • 隐式的赋值语句使自动变量在程序执行到它们所声明的函数(或代码块)时,每次都将重新初始化;(关于隐式赋值和显式赋值可以参考这个文章:关于编程语言中的显式\隐式初始化)
  • 优点:由于初始化在运行时执行,你可以用任何表达式作为初始化值;
  • 除非你对自动变量进行显式的初始化,否则当自动变量创建时,它们的值总是垃圾。

2. 静态变量(static)

变量的缺省存储类型取决于它的声明位置。凡是在任何代码块之外声明的变量总是存储于静态内存中,也就是不属于堆栈的内存,这类变量称为静态(static)变量

对于这类变量,无法为它们指定其他存储类型。静态变量在程序运行之前创建,在程序的整个执行期间始终存在它始终保持原先的值,除非给它赋一个不同的值或者程序结束

对于在代码块内部声明的变量,如果给它加上关键字static,可以使它的存储类型从自动变为静态。注意,修改变量的存储类型并不表示修改该变量的作用域,它仍然只能在该代码块内部按名字访问。函数的形式参数不能声明为静态,因为实参总是在堆栈中传递给函数,用于支持递归

2.1 静态变量的初始化

在静态变量的初始化中,我们可以把可执行程序文件想要初始化的值放在当程序执行时变量将会使用的位置。当可执行文件载入到内存时,这个已经保存了正确初始值的位置将赋值给那个变量完成这个任务并不需要额外的时间,也不需要额外的指令,变量将会得到正确的值如果不显式地指定其初始值,静态变量将初始化为0

3. 寄存器变量(register)

关键字register可以用于自动变量的声明,提示它们应该存储于机器的硬件寄存器而不是内存中,这类变量称为寄存器变量。通常,寄存器变量比存储于内存的变量访问起来效率更高。但是,编译器并不一定要理睬register关键字,如果有太多的变量被声明为register,它只选取前几个实际存储于寄存器中,其余的就按普通自动变量处理。如果一个编译器自己具有一套寄存器优化方 法,它也可能忽略register关键字,其依据是由编译器决定哪些变量存储于寄存器中比人脑的决定更为合理一些。

在典型情况下,你希望把使用频率最高的那些变量声明为寄存器变量。在有些计算机中,如果把指针声明为寄存器变量,程序的效率将能得到提高,尤其是那些频繁执行间接访问操作的指针。你可以把函数的形式参数声明为寄存器变量,编译器会在函数的起始位置生成指令,把这些值从堆栈复制到寄存器中。但是,完全有可能,这个优化措施所节省的时间和空间的开销还抵不上复制这几个值所用的开销。

寄存器变量的创建和销毁时间和自动变量相同,但它需要一些额外的工作。在一个使用寄存器变量的函数返回之前,这些寄存器先前存储的值必须恢复,确保调用者的寄存器变量未被破坏。许多机器使用运行时堆栈来完成这个任务。当函数开始执行时,它把需要使用的所有寄存器的内容都保存到堆栈中,当函数返回时,这些值再复制回寄存器中。

在许多机器的硬件实现中,并不为寄存器指定地址。同样,由于寄存器值的保存和恢复,某个特定的寄存器在不同的时刻所保存的值不一定相同。基于这些理由,机器并不向你提供寄存器变量的地址

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

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

相关文章

JAVA宝典----容器(理解记忆)

目录 一、Java Collections框架是什么&#xff1f; 二、什么是迭代器&#xff1f; 三、Iterator与ListIterator有什么区别&#xff1f; 四、ArrayList、Vector和LinkedList有什么区别&#xff1f; 五、HashMap、Hashtable、TreeMap和WeakHashMap有哪些区别&#xff1f; 六…

专门针对开发人员,攻击者利用Rust获取操作系统信息

近日&#xff0c;研究人员在 Rust 编程语言的 crate 注册表中发现了一些恶意软件包&#xff0c;专门针对开发人员。 Phylum 在上周发布的一份报告中称&#xff0c;这些库是由一个名为 "amaperf "的用户在 2023 年 8 月 14 日至 16 日之间上传的。现已删除的软件包名…

【设计模式】Head First 设计模式——桥模式 C++实现

设计模式最大的作用就是在变化和稳定中间寻找隔离点&#xff0c;然后分离它们&#xff0c;从而管理变化。将变化像小兔子一样关到笼子里&#xff0c;让它在笼子里随便跳&#xff0c;而不至于跳出来把你整个房间给污染掉。 设计思想 桥模式。将抽象部分(业务功能)与实现部分(平…

Nat. Commun.2023 | AI-Bind+:提高蛋白质配体结合预测的通用性

论文标题&#xff1a;Improving the generalizability of protein-ligand binding predictions with AI-Bind 论文地址&#xff1a;Improving the generalizability of protein-ligand binding predictions with AI-Bind | Nature Communications 代码&#xff1a; Barabasi…

WEBGL(2):绘制单个点

代码如下&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevi…

安防监控/视频存储/视频汇聚平台EasyCVR接入海康Ehome车载设备出现收流超时的原因排查

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。视频汇聚平台既具…

yolov5 应用整理

yolov5 应用整理 适用于0基础人员与有一定yolov5了解的人员食用. 关于yolov5参考: yolov5 github源码链接 目前参与过yolov5的应用: 平台库x86/arm cpuncnnx86libtorch/pytorchBM1684算能标准库(需要进行模型转换)昇腾cann(ascend api) https://gitee.com/Tencent/ncnn ht…

Google Earth Engine 的缺点和限制

随着 Google Earth Engine 在地球科学和数据计算领域越来越流行&#xff0c;网上有很多介绍Google Earth Engine 的文章及 Google Earth Engine的追随者。Google Earth Engine确实是一款伟大的产品&#xff0c;我们应该为其点赞。但由于已经有太多人在热捧了&#xff0c;我这里…

构造函数和析构函数(个人学习笔记黑马学习)

构造函数:主要作用在于创建对象时为对象的成员属性赋值&#xff0c;构造函数由编译器自动调用&#xff0c;无须手动调用。析构函数:主要作用在于对象销毁前系统自动调用&#xff0c;执行一些清理工作。 #include <iostream> using namespace std;//对象初始化和清理class…

小程序中如何给会员卡设置到期时间

通过设置会员卡到期时间&#xff0c;可以有效地管理会员卡的使用周期&#xff0c;提供更好的会员服务体验。下面将介绍一种常见的给会员卡设置到期时间的方法。 1. 找到指定的会员卡。在管理员后台->会员管理处&#xff0c;找到需要设置到期时间的会员卡。也支持对会员卡按…

解决springboot项目中的groupId、package或路径的混淆问题

对于像我一样喜欢跳跃着学习的聪明人来说&#xff0c;肯定要学springboot&#xff0c;什么sevlet、maven、java基础&#xff0c;都太老土了&#xff0c;用不到就不学。所以古代的聪明人有句话叫“书到用时方恨少”&#xff0c;测试开源项目时&#xff0c;编译总是报错&#xff…

EVO大赛是什么

价格是你所付出的东西&#xff0c;而价值是你得到的东西 EVO大赛是什么&#xff1f; “EVO”大赛全称“Evolution Championship Series”&#xff0c;是北美最高规格格斗游戏比赛&#xff0c;大赛正式更名后已经连续举办12年&#xff0c;是全世界最大规模的格斗游戏赛事。常见…