c++ - 为什么 [intro.execution]/12 认为访问 volatile glvalue 是副作用?

标签 c++ language-lawyer volatile

[intro.execution]/12 中术语 volatile 的相关性是什么?

[intro.execution]/12 :

Reading an object designated by a volatile glvalue ([basic.lval]), modifying an object, calling a library I/O function, or calling a function that does any of those operations are all side effects, which are changes in the state of the execution environment. Evaluation of an expression (or a sub-expression) in general includes both value computations (including determining the identity of an object for glvalue evaluation and fetching a value previously assigned to an object for prvalue evaluation) and initiation of side effects. When a call to a library I/O function returns or an access to a volatile object is evaluated the side effect is considered complete, even though some external actions implied by the call (such as the I/O itself) or by the volatile access may not have completed yet.

最佳答案

volatile 的全部目的是向编译器表明“你并不真正知道访问这个变量的确切结果是什么,所以不要乱搞它”。

比如说我们有:

 int x = 7;
 ...
 int func1()
 {
   return x;
 }
 ...
 int func2()
 {
    return func1() + func1();
 }

编译器可以(有些人认为应该)将其转换为 return 2 * func1(); [这是通过一次加法简单计算的]。

但是,如果 x 是一个硬件寄存器 [因此 return x; 实际上表现得像 return x++;],它随着每个读取(例如,它是一个计数器寄存器),则 func1()+func1() 不能也不应优化为 2 * func1(); - 以避免这样做的编译器 volatile int x; 将使这种情况发生[不幸的是,没有办法在纯 C++ 代码中导致这种行为/需要一些真实的硬件]

硬件寄存器,这是 volatile 的正常用例(通常与指针结合使用,但并非必须如此),寄存器的读取可能会产生实际的副作用在硬件上——例如读取串行端口[或网卡、硬盘或其他]上的 fifo 寄存器将影响硬件的状态,因为 fifo 现在“向前移动”了一步。跳过、复制、缓存结果或其他一些此类优化肯定会导致一段驱动程序代码和硬件以不同于程序员想要的方式运行——如果 volatile 就会出现这种情况不被认为有副作用。

关于c++ - 为什么 [intro.execution]/12 认为访问 volatile glvalue 是副作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34840115/

相关文章:

c++ - 如何在 OpenGL 中使用 SDL2 软件渲染?

c++ - 在 C++ 中,在 STL 容器中存储具有重载 "operator&"的类对象是否合法?

c++ - 将 n 个 vector 组合成一个 n 元组 vector

c - printf() 的字符串宽度对于未终止的字符串是否安全?

c++ - 是什么让 union 成员(member)活跃起来?

c++ - 实现一个没有未定义行为的类似 std::vector 的容器

c - C 编译器是否可以随意重写数组中的相邻值?

java - 为什么同步的 getter 像 volatile read 一样工作?

c - volatile 和序列点

c++ - 无法链接CMake中的本地库