首页 / 知识
关于c ++:为什么存在volatile?
2023-04-15 22:42:00

Why does volatile exist?
就我而言,我从来没有故意需要它。
如果您正在从内存中的某个位置读取,例如,一个完全独立的进程/设备/可能写入的内容,则需要 我曾经在直接C的多处理器系统中使用双端口ram。我们使用硬件管理的16位值作为信号量来知道其他人何时完成。基本上我们这样做了:
如果没有
在开发嵌入式系统或设备驱动程序时需要 一些处理器具有超过64位精度的浮点寄存器(例如,没有SSE的32位x86,参见Peter的评论)。这样,如果对双精度数运行多个操作,实际上得到的答案要比将每个中间结果截断为64位时更高。 这通常很好,但这意味着根据编译器分配寄存器的方式和优化,您将在完全相同的输入上对完全相同的操作产生不同的结果。如果需要一致性,则可以使用volatile关键字强制每个操作返回内存。 它对于一些没有代数意义但减少浮点误差的算法也很有用,例如Kahan求和。代数上它是一个nop,因此除非某些中间变量是易失性的,否则它往往会被错误地优化出来。 来自Dan Saks的"挥发性如诺"文章:
以下是关于
在实现无锁数据结构时,您必须使用volatile。否则,编译器可以自由地优化对变量的访问,这将改变语义。 换句话说,volatile告诉编译器访问此变量必须对应于物理内存读/写操作。 例如,这是在Win32 API中声明InterlockedIncrement的方式:
我在20世纪90年代早期使用的大型应用程序包含使用setjmp和longjmp的基于C的异常处理。 volatile的关键字对于需要在作为"catch"子句的代码块中保留的变量是必要的,以免这些变量存储在寄存器中并被longjmp消灭。
在标准C中,使用
这意味着在标准C中,您可以写:
而不是其他。
POSIX对于您在信号处理程序中可以执行的操作更加宽容,但仍存在一些限制(其中一个限制是标准I / O库 - 为嵌入式开发,我有一个循环,它检查可以在中断处理程序中更改的变量。如果没有"volatile",循环就会变成noop - 就编译器而言,变量永远不会改变,因此它会优化检查。 同样的事情适用于在更传统的环境中可能在不同线程中更改的变量,但是我们经常进行同步调用,因此编译器不是那么自由的优化。 我已经在调试版本中使用它,当编译器坚持优化我希望能够在逐步执行代码时看到的变量。 除了按预期使用它之外,在(模板)元编程中使用volatile。它可用于防止意外过载,因为volatile属性(如const)参与重载决策。
这是合法的;两个重载都可以调用,并且几乎完全相同。
请注意,代码实际上从不依赖于
声明为 考虑以下情况 1)由范围外的中断服务例程修改的全局变量。 2)多线程应用程序中的全局变量。 如果我们不使用volatile限定符,可能会出现以下问题 1)打开优化时,代码可能无法按预期工作。 2)启用和使用中断时,代码可能无法正常工作。 易失性:程序员最好的朋友 https://en.wikipedia.org/wiki/Volatile_(computer_programming) 在C的早期,编译器会将读取和写入左值作为内存操作的所有操作解释为与代码中出现的读写相同的序列。如果编制者获得一定程度的自由来重新订购和整合运营,那么在许多情况下效率可以大大提高,但是存在问题。甚至操作通常仅按某种顺序指定,因为有必要按某种顺序指定它们,因此程序员选择了许多同样好的替代方案中的一种,但情况并非总是如此。有时某些操作以特定顺序发生是很重要的。
确切地说,排序的哪些细节很重要,具体取决于目标平台和应用领域。标准选择了一个简单的模型,而不是提供特别详细的控制:如果使用不合格的左值(
不幸的是,许多编制者选择提供标准规定的最低限度保证,而不是确定程序员需要什么样的保证。这使得 将互斥锁的获取和释放放在编译器无法内联的函数中,并且不能应用整个程序优化。
将互斥锁保护的所有对象限定为
使用优化级别0强制编译器生成代码,就好像所有非限定 使用特定于gcc的指令。 相比之下,当使用更适合系统编程的更高质量的编译器(例如icc)时,可以有另一种选择:
获取一个基本的"切换互斥锁"需要一个
即使没有
如前所述,
但是,一旦调用外部或非内联函数,似乎几乎没有效果。例如。:
然后在有或没有 只要g()可以完全内联,编译器就可以看到正在进行的所有事情,因此可以进行优化。但是当程序调用一个编译器无法看到正在发生的事情的地方时,编译器不再需要做出任何假设是不安全的。因此,编译器将生成始终直接从内存中读取的代码。
但要注意当天,当函数g()变为内联时(由于显式更改或由于编译器/链接器的聪明性),如果忘记
因此,我建议添加 除了volatile关键字用于告诉编译器不优化对某个变量的访问(可以通过线程或中断例程修改)之外,它还可以用于删除一些编译器错误 - 是的,它可以是---。 例如,我在嵌入式平台上工作的是编译器对变量值进行了一些错误的分析。如果代码没有优化,程序将运行正常。通过优化(这是真正需要的,因为它是一个关键的例程)代码将无法正常工作。唯一的解决方案(虽然不是很正确)是将'faulty'变量声明为volatile。 我应该提醒您的一个用途是,在信号处理函数中,如果要访问/修改全局变量(例如,将其标记为exit = true),则必须将该变量声明为"volatile"。 |
最新内容
相关内容
linuxmv命令作用?
linuxmv命令作用?,系统,文件,命令,名称,目录,文件夹,源文件,缩写,参数,目标,linux中mv命令使用详解mv命令是move的缩写,可以用来移动文件或者将linux查看系统盘命令?
linux查看系统盘命令?,情况,系统,信息,工具,服务,管理,命令,软件,单位,状态,如何在linux红帽子系统下查看磁盘阵列空间大小?用什么命令?软件ra麒麟系统有linux命令吗?
麒麟系统有linux命令吗?,系统,银河,公司,软件,平台,麒麟,国家,服务,环境,等级,国产麒麟操作系统到底是不是用linux的内核,谁告诉我答案.1、高linux登录系统的命令?
linux登录系统的命令?,系统,工作,地址,名称,网络,密码,信息,服务,软件,资料,linux系统下的Login,Logout,Reboot,Halt,Exit,Poweroff,Shutdownlinux读取命令行参数?
linux读取命令行参数?,系统,信息,数据,名称,软件,位置,标准,灵活,百度,资料,Linux命令行操作之sedsed命令行格式为:sed [-nefri] ‘command’linux还原系统命令?
linux还原系统命令?,系统,数据,设备,工具,电脑,一致,命令,硬盘,文件,备份,linux系统里restore命令如何使用1、呃,实际上这并不是一项系统功能,至linux系统时钟命令?
linux系统时钟命令?,时间,系统,命令,信息,城市,网上,资料,时区,终端,时分,linux修改时间1、inux修改时间命令是date-s+时分秒。修改linux系统linux系统做镜像命令?
linux系统做镜像命令?,系统,设备,网上,发行,数据,工具,电脑,信息,代码,软件,Linux怎么制作可启动img/iso镜像文件一个U盘。一个ISO或IMG格式的linux系统删除的命令?
linux系统删除的命令?,软件,系统,名称,工具,不了,命令,文件夹,电脑,通用,信息,linux删除文件夹命令1、linux删除命令rm-rf命令。具体详情:rm命linux系统自检命令?
linux系统自检命令?,系统,服务,信息,电脑,情况,管理,状态,检测,异常,命令,Linux下怎样检测进程是否异常1、ps命令是最基本同时也是非常强大的linux系统命令添加?
linux系统命令添加?,系统,密码,代码,简介,命令,实战,项目,工作,资料,基础,linux系统添加用户命令是什么?1、打开xshell软件,远程访问您的服务器常用的linux命令作用?
常用的linux命令作用?,工作,系统,信息,管理,地址,时间,命令,目录,平均,项目,linux常用命令及用法1、linux系统常用操作命令如下:ls:全拼list,功能