当前位置: 首页 > news >正文

C语言register关键字与volatile关键字

CPU的基本组成

要讲这个,我们先要介绍一下CPU的组成
CPU由运算器与控制器组成,而现代CPU内部通常也集成了存储器
这里这个存储器又包含:

  • 寄存器
  • L1 Cache(一级缓存)
  • L2 Cache(二级缓存)
  • L3 Cache(三级缓存)
    其中下面三个可以统称为CPU缓存。
    寄存器就是被CPU直接操控的数据存储区
    而缓存是CPU和内存之间的缓冲区
    而在CPU外部,还有一个存储设备RAM,就是我们常说的内存
存储单元容量速度位置
寄存器几十~几百字节最快CPU核心内部
L1 Cahce几十KB极快CPU核心内部
L2 Cache几百KB~数MB很快CPU核心内部
L3 Cache几MB~数十MB较快多核心共享
RAMGB级较慢CPU外部

缓存的作用可以这样说,假如一个程序要利用一个数组[1,2,3,4,5]的所有数据,但是如果每次读一个数据都要通过总线从内存拿,这样效率会有一点低下。我们在运行这个程序的时候可以直接把[1,2,3,4,5]这整个数组先拿到缓存里,这样后续访问就会快很多。
本质区别可以用这两句话概括:
寄存器:

CPU正在计算的数据

缓存:

CPU未来可能要计算的数据

register关键字

我们直接看最本质、最核心的区别:

#include<stdio.h> int main() { int m = 1; while(1) { printf("%d",m); } return 0; }

这段代码写了一个死循环,一直输出变量m的值
但是,这有一个问题会影响效率。在我们程序运行时,程序会从硬盘中被拉取到内存中。每一次循环,都要执行一次打印m的值的语句,而这个语句每次执行都要CPU通过总线从内存中读取变量m的值,这就会影响效率。但是解决很简单,这样写就可以解决这个问题:

#include<stdio.h> int main() { register int m = 1; while(1) { printf("%d",m); } return 0; }

对比可以发现,和上一个代码的区别仅仅是这个代码在定义变量m的时候多了一个register关键字。
register关键字的作用就是,建议编译器把我们定义的变量放入CPU寄存器。
看我们的代码,如果变量m被放入了寄存器,那么在while每一次循环都不需要再与内存交互而是直接从寄存器中读取变量m的值,大大提高了程序运行效率。
几个注意点:

  • 加了register关键字并不代表编译器一定会把这个变量存在寄存器,只是建议编译器把这个变量存在寄存器,具体要看寄存器的空间情况。
  • register关键字只能修饰局部变量的定义,不能修饰全局变量的定义和函数定义。
  • 不能使用取地址运算符&对被register关键字标记的变量进行取地址运算。因为取地址运算符只能对在内存中的变量获得其内存地址,而寄存器中的变量压根不在内存中。
  • register修饰的变量一定要是CPU所能处理的类型(比如有的CPU不支持浮点,用register标记浮点就会出问题
  • register适用于标记某一个被频繁使用的变量
    不过,在早期的C语言编译器中,register非常有用。但是,现代编译器(如 GCC, Clang)的优化算法(比如开启-O2-O3优化)已经非常强大了。编译器自己就能完美判断出哪些变量被频繁使用,并自动将它们放入寄存器中。但是我们依然要重视这个关键字的使用。

volatile关键字

volatile在英文中的意思是异变的、动荡不定的
volatile关键字的作用是标记被这个关键字修饰的变量随时可能发生变化
可以看这个例子

#include<stdio.h> int main() { int flag = 0; while(flag==0) { } return 0; }

这里编译器会发现while循环内部压根就没有修改flag的,但是每次循环结束后都要判断一次flag==0,这时候就会进行编译器优化,把flag这个变量拿到寄存器内部,不再利用内存中的flag变量。这就会出现一个问题,如果内存中的flag变量真的被修改了,那么flag不是0了,按理来说循环应该结束,但是还是会执行。
这时候就可以对flagvolatile关键字进行修饰,这样就会阻止编译器优化。绝大部分情况下用于全局变量。
代码如下:

#include<stdio.h> int main() { volatile int flag = 0; while(flag==0) { } return 0; }

总结

这两个关键字都与CPU的寄存器与内存的管理有关,两者有类似之处,一个是建议把变量定义在寄存器中,一个是建议不把变量拉到寄存器中。

http://www.jsqmd.com/news/1033001/

相关文章:

  • Seraphine:3分钟掌握英雄联盟实时战绩查询与智能BP技巧
  • OptiScaler完整指南:5个步骤解锁游戏画质与帧率双重提升
  • Flow Matching for Generative Models-从generalized的角度来理解diffusion模型
  • LinkSwift:一键获取九大网盘直链下载地址的终极免费方案
  • Adobe Illustrator脚本集合:设计师必备的70+效率倍增器
  • 2026辛安街道专业的空调拆卸公司推荐榜 - 品牌排行榜
  • Ubuntu系统下WiFi Monitor模式的实战配置与网络诊断
  • 一文读懂4J36(因瓦合金)国内全产业链供应格局 - 品牌2026
  • PostgreSQL数据库建模终极指南:5分钟掌握免费可视化设计神器
  • NetEase-Cloud-Music-DiscordRPC:如何让你的Discord好友随时知道你在听什么音乐?
  • Java毕业设计-基于 Spring Boot 的个人博客网站的设计与实现 基于 Spring Boot 的轻量化个人博客发布平台(源码+LW+部署文档+全bao+远程调试+代码讲解等)
  • CMLM-ZhongJing中医大语言模型:从零开始的完整入门指南
  • LunaTranslator终极指南:三步实现视觉小说实时翻译的完整教程
  • 【最新】Maven下载安装配置保姆级图文教程(附安装包+图文步骤)
  • MaxBot抢票机器人:您的多平台自动化抢票终极解决方案
  • AI vs AI:工业级对抗系统构建与鲁棒性实战指南
  • 如何快速解密网易云音乐ncm文件:Windows图形界面工具完整指南
  • 深度解析17-4PH线材特性,揭秘国内几家具备精密加工能力的优质厂商 - 品牌2026
  • i.MX31 PDK 1.4硬件平台深度解析:从ARM11核心到嵌入式系统开发实战
  • IEEE 802.15.4 MAC层数据结构与状态枚举深度解析
  • GLM-4.7升级实战指南:Tokenizer重构与多跳推理新范式
  • 2026年上海劳动合同纠纷顾问哪家好?5家专业推荐 - 本地品牌推荐
  • 1.3 FastAPI → Django → Vue → React 面试题
  • GPT-4 Turbo工程落地:128K上下文、时效知识与多模态实战指南
  • 如何用openpilot免费升级你的汽车:终极智能驾驶辅助指南
  • 我做的那个东西,真的有人在用吗?
  • 上海崇明区黄金回收商家梯队排行:高价透明款都在这,性价比一目了然 - 沪上贵金属口碑推荐官
  • PostgreSQL数据库设计终极指南:5分钟掌握PGModeler高效建模
  • 终极指南:如何用noScribe将学术访谈转录效率提升300%
  • LegacyUpdate终极指南:如何修复Windows Update错误80072EFE并恢复旧系统更新功能