当前位置: 首页 > 知识库问答 >
问题:

标准在哪里定义了可变变量可以更改?

周越泽
2023-03-14

标准在哪里定义易失性变量可以在未被检测到的情况下发生变化?

我发现了两个关于不稳定的规范性文本:

简介。执行/7:

读取由volatile glvalue([basic.lval])指定的对象、修改对象、调用库I/O函数或调用执行这些操作的函数都是副作用,这些都是执行环境状态的变化。表达式(或子表达式)的计算通常包括值计算(包括确定用于glvalue计算的对象的标识和获取之前分配给对象用于prvalue计算的值)和副作用的启动。当对库I/O函数的调用返回或通过易失性glvalue的访问被评估时,即使调用(如I/O本身)或易失性访问暗示的某些外部操作可能尚未完成,副作用也被视为已完成。

这一段是关于未被发现的变化吗?副作用可能是这个意思吗?

或者有dcl。类型简历/5:

通过易失性glvalue访问的语义学是实现定义的。如果尝试通过使用非易失性glvalue访问使用易失性限定类型定义的对象,则行为是未定义的。

这一段是关于我的问题吗?“通过易失性glvalue进行访问的语义是实现定义的”到底意味着什么?你能举例说明不同的“访问语义”吗?

还有dcl。类型简历6,关于我的问题,但这只是一个注释:

[ 注意:volatile是对实现的一种提示,以避免涉及对象的激进优化,因为对象的值可能会通过实现无法检测到的方式进行更改。此外,对于某些实现,volatile可能表示访问对象需要特殊的硬件指令。有关详细的语义,请参见[简介执行]。一般来说,volatile的语义在C中与在C中相同- 结束注释 ]

共有2个答案

方砚
2023-03-14

易失性只是对编译器的请求,要求它为每次访问从内存中重新加载变量。它适用于2个常见用例:

  • 变量可以被不同的线程(甚至可以被授予对该内存区域的写访问权限的不同程序)或内核模式代码(例如通过特殊驱动程序)更改
  • 这个变量代表一个物理内存寄存器,主要用于内核模式编程,或者在没有用户/内核模式概念的操作系统上,如旧的MS/DOS。

一旦您知道了这一点,标准中的不同引用都是有意义的。

正在读取由易失性glvalue([basic.lval])指定的对象。。。都是副作用,即执行环境状态的变化。

读取硬件寄存器可能会对底层系统产生影响,这就是为什么它被称为可观察到的副作用的原因。

通过易失性glvalue访问的语义学是实现定义的。如果尝试通过使用非易失性glvalue访问使用易失性限定类型定义的对象,则行为是未定义的。

如果使用非易失性指针访问易失性硬件寄存器,编译器可能会缓存以前的值,而不会执行物理访问。

[ 注意:volatile是对实现的一种提示,以避免涉及对象的激进优化,因为对象的值可能会通过实现无法检测到的方式进行更改。此外,对于某些实现,volatile可能表示访问对象需要特殊的硬件指令。有关详细的语义,请参见[简介执行]。一般来说,volatile的语义在C中与在C中相同- 结束注释 ]

一些实现可以为特殊的低级别io端口操作保留内存区域。在这种情况下,可能需要volatile说明符和特殊内存区域地址的组合来验证转换或具有特殊io操作的正常内存访问操作。

云利
2023-03-14

这里的关键是“执行环境状态的变化”

执行环境是程序外部的环境。这可能包括操作系统、文件系统、屏幕等等。这通常是不可预测的。您不能假设如果将0写入文件,则该文件不会被另一个进程用1覆盖。

volatile变量在逻辑上是该执行环境的一部分。就C而言,环境可以枚举、读取和写入它们,就像文件一样。这可能在您的程序不知道的情况下发生。

另一方面,你的实现实现了你的程序和它的执行环境之间的联系,所以它确实知道可能会发生什么。如果它有某种私有RAM磁盘实现,那么它可能知道某些文件名在操作系统文件系统中是不可见的。它可能知道易失性int i存在于CPU寄存器中,因此无法通过内存映射访问它。这都是C标准允许的。它只是笼统地谈论了执行环境,实现必须更加精确。这就是“实现定义的语义学”的意思。

 类似资料:
  • 我想看一下 SQL 标准中的内容 然后我去谷歌搜索了一下 chatGPT 给我的关键字 但是出来的结果,貌似都是和某一款 DB 具体实现相关,而不是一个通用的 sql 标准

  • 变量绑定默认是不可变的,但加上 mut 修饰语后变量就可以改变。 fn main() { let _immutable_binding = 1; let mut mutable_binding = 1; println!("Before mutation: {}", mutable_binding); // 正确代码 mutable_binding += 1

  • 我想用Ansible复制大文件。目标服务器有一个具有足够存储空间的专用分区。我注意到ansible使用由remote_tmp变量定义的临时目录。 谢谢你的回答。

  • 问题内容: 我想尝试查找Python标准库中某些模块的源代码,但找不到它们。下载python tarball后,我尝试在modules目录中查找,但是它主要包含.c文件。我还尝试查看了OS(mac osx)随附的python所在的目录,该目录中包含它的模块,并且那里似乎主要包含.pyc和.pyo文件。如果有人可以帮助我,我将不胜感激。 (我尝试了问题“如何找到Python模块源的位置?”中的建议,

  • 问题内容: 我的crontab每小时运行一次。当用户从终端运行作业时,运行它的用户在工作中具有环境变量,但是,显然,crontab在运行时不会被环境变量吸收。 我尝试过将它们放入,但是它们似乎仍然没有被捡起。有谁知道我可以将crontab可以接收的环境变量放在哪里? 问题答案: 在运行命令之前,让’cron’运行一个设置环境的shell脚本。 总是。 〜/ bin / Cron中的脚本都是指向单个

  • 问题内容: 我如何在for循环中创建变量变量? 这是循环: 在此循环中,我想为每次传递创建一个$ seat变量,但必须像这样递增。第一次通过应该是,下次通过:等等。 所以最后应该是: 等等。 因此$ _POST的变量和内容应该是动态的。 问题答案: 首先,除非缺少某些内容,否则我将为此使用数组。具有像变量,等趋于具有少得多的效用和是更为繁琐比使用的阵列。 话虽这么说,使用以下语法: 最后,PHP具