C ++编译器能否消除非读取的易失性本地Var

时间:2013-05-24 10:23:01

标签: c++ visual-c++ c++11 volatile intrinsics

说,我有这段代码:

int f() {
  volatile int c;
  c=34;
  return abc();
}

永远不会读取 volatile int c 。但它被标记为 volatile ,编译器可以完全消除它吗?我在Visual C ++ 2010中的测试显示了相互矛盾的结果。在VC ++中,如果我启用优化(最大化速度),上面的函数包含一个名为c的局部变量(通过查看生成的程序集列表)。但是,我没有使用赋值运算符,而是尝试通过编译器内部函数(如memset()初始化变量(并使用编译器内部函数启用),该变量被消除。

int f() {
  volatile int c;
  memset((void*)&c,34, 1); 
  return abc();
}

所以根据C ++标准,编译器可以消除volatile int c吗?我想可能VC ++中存在一些与内部函数如何优化volatile变量有关的不一致行为。

2 个答案:

答案 0 :(得分:7)

memset((void*)&c,34, 1);有未定义的行为(第7.1.6.1 / 6节)。因此允许编译器产生任何结果。

  

如果尝试通过使用具有非volatile限定类型的glvalue来引用使用volatile限定类型定义的对象,则程序行为未定义。

请不要使用那样的演员表,更不要使用C风格的演员阵容了。当一个人不知道在某种情况下正确的C ++演员是什么时,很可能是一个不应该投出任何东西的情况。

答案 1 :(得分:4)

  

所以根据C ++标准,编译器是否可以消除volatile int c?

即可。 volatile - 限定对象用于读取或写入硬件,并且可以观察到分配volatile对象的副作用。

因此,根据所谓的"as-if" rule对优化的限制,不允许符合要求的实现优化c。 “ as-if ”规则在C ++ 11标准的第1.9 / 1段中正式引入:

  

本国际标准中的语义描述定义了参数化的非确定性摘要   机。本国际标准对符合实施的结构没有要求。   特别是,它们不需要复制或模拟抽象机器的结构。相反,符合   如上所述,实现需要模拟(仅)抽象机器的可观察行为   以下

可观察行为”的概念在第1.9 / 8段中定义:

  

符合实施的最低要求是:

     

- 严格按照抽象机的规则评估对易失性对象的访问。

     

- 在程序终止时,写入文件的所有数据应与其中一个可能的结果相同   根据抽象语义执行程序会产生。

     

- 交互设备的输入和输出动态应以提示的方式进行   输出实际在程序等待输入之前传送。什么构成了交互设备   是实现定义的。

     

这些统称为程序的可观察行为 。 [...]

由于必须严格按照抽象机器的规则评估对volatile对象的访问,因此不允许编译器优化c和相应的赋值操作。