为什么通过[intro.execution] / 12将对易失性glvalue的访问视为副作用?

时间:2016-01-17 15:33:58

标签: c++ language-lawyer volatile

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

[intro.execution]/12

  

读取由volatile glvalue([basic.lval])指定的对象,   修改对象,调用库I / O函数或调用   执行任何这些操作的功能都是副作用   是执行环境状态的变化。评估   表达式(或子表达式)通常包括两个值   计算(包括确定对象的身份)   glvalue评估并获取先前分配给的值   prvalue评估的对象)和副作用的启动。当一个   调用库I / O函数返回或访问volatile   对象被评估,副作用被认为是完整的,甚至   虽然呼叫隐含了一些外部动作(例如I / O.   本身)或由易失性访问可能还没有完成。

1 个答案:

答案 0 :(得分:5)

volatile的全部目的是向编译器表明"您并不确切知道访问此变量的结果是什么,所以不要搞砸了它&#34 ;.

比如我们说:

 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不是&#39则会出现这种情况。 ;被认为有副作用。