4

说,我有这个代码:

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 变量相关的不一致行为。

4

2 回答 2

7

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

如果尝试通过使用具有非易失性限定类型的泛左值来引用具有易失性限定类型定义的对象,则程序行为是未定义的。

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

于 2013-05-24T11:26:51.383 回答
4

那么根据 C++ 标准,编译器可以消除 volatile int c 吗?

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

因此,按照所谓的“as-if”规则对优化的约束,不允许符合的实现优化掉c。“ as-if ”规则在 C++11 标准的第 1.9/1 段中正式引入:

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

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

对一致性实现的最低要求是:

对 volatile 对象的访问严格按照抽象机的规则进行评估

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

— 交互式设备的输入和输出动态应以这样一种方式发生,即在程序等待输入之前实际提供提示输出。构成交互式设备的内容是实现定义的。

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

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

于 2013-05-24T10:27:25.363 回答