标准定义了volatile变量可以改变的位置?

gez*_*eza 9 c++ volatile language-lawyer c++17

标准定义了哪个volatile变量可以不被检测到?

我发现了两个关于volatile的规范性文本:

intro.execution/7:

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

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


或者有dcl.type.cv/5:

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

这个段落是关于我的问题吗?什么"通过volatile glvalue进行访问的语义是实现定义的"究竟是什么意思?你能举一个不同的"访问语义"的例子吗?


还有dcl.type.cv/6,这是关于我的问题,但它只是一个注释:

[注意:volatile是对实现的暗示,以避免涉及对象的激进优化,因为对象的值可能会被实现无法检测到的方式更改.此外,对于某些实现,volatile可能指示访问对象需要特殊的硬件指令.有关详细语义,请参阅[intro.execution].一般来说,volatile的语义在C++中与在C中的相同. - 最后的注释]

MSa*_*ers 7

这里的关键是"执行环境状态的变化".

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

volatile变量在逻辑上是该执行环境的一部分.就C++而言,环境可以枚举它们,读取它们并编写它们,就像文件一样.这可以在你的程序不知情的情况下发生.

另一方面,您的实现实现了程序与其执行环境之间的链接,因此它确实可以了解可能发生的情况.如果它具有某种私有RAM磁盘实现,那么它可能知道某些文件名在OS文件系统中不是外部可见的.它可能知道它volatile int i存在于CPU寄存器中,因此无法通过内存映射进行访问.这一切都是C++标准所允许的.它只是概括地谈论执行环境,实现必须更加精确.这就是"实现定义的语义"的含义.