c++编译器能否消除未读的易失性局部变量?
visual Can a C++ Compiler Eliminate a Volatile Local Var that is not Read
比如说,我有这样的代码:
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 ?我认为可能有一些不一致的行为在vc++有关如何内在函数优化易失性变量。
memset((void*)&c,34, 1);
具有未定义的行为(§7.1.6.1/6)。因此,编译器可以产生任何结果。
如果试图通过使用具有非易失性限定类型的glvalue来引用用易失性限定类型定义的对象,则程序的行为是未定义的。
请不要使用这样的强制转换,更不用说c风格的强制转换了。当不知道特定情况下正确的c++强制类型转换是什么时,很可能是不应该强制类型转换的情况。
没有那么根据c++标准,编译器能否消除volatile int ?
。volatile
限定对象用于对硬件进行读写,分配volatile
对象的副作用是可以观察到的。
因此,根据所谓的"as-if"规则对优化的约束,不允许符合的实现优化掉c
。"as-if"规则在c++ 11标准的第1.9/1段中正式引入:
本国际标准中的语义描述定义了一个参数化的不确定性抽象机器。本国际标准对一致性实现的结构没有要求。特别是,它们不需要复制或模拟抽象机器的结构。相反,符合如前所述,实现需要模拟(仅)抽象机器的可观察行为在
"可观察行为"的概念在第1.9/8段中定义:
一致性实现的最低要求是:
- 对易失性对象的访问严格按照抽象机的规则求值。
-在程序结束时,写入文件的所有数据应与程序执行时可能得到的结果之一相同根据抽象语义执行程序将产生。
—交互设备的输入和输出动态应以这样一种方式发生:提示输出实际上是在程序等待输入之前交付的。什么是互动设备是由实现定义的。
这些统称为程序的可观察行为。[…]
由于对volatile
对象的访问必须严格按照抽象机的规则求值,编译器不允许优化去掉c
和相应的赋值操作。
- 易失性sig_atomic_t的内存安全性
- C++易失性:保证 32 位访问?
- 避免易失性和非易失性成员函数的代码重复
- 当 2 个线程共享同一物理内核时,具有错误共享的易失性增量在发布中的运行速度比在调试中慢
- 是否允许编译器优化掉局部易失性变量
- 兼容的声明 __attribute__ ((节( ".abc.dfe" ))) 常量易失性 uint8 属性变量 = 0;- 符合MISRA标准
- 常量 & 指非易失性变量。变量将更改。更改是否使常量 & 无效?
- 如何使用 LLVM 传递使变量易失性或常量
- 优化易失性堆栈变量的存储/构造是否合法
- C++变量定义中的易失性类型量词位置
- 非易失性变量
- 在 C++ 中易变:我是否应该定义一个可能被几个线程更改的变量作为易失性
- 使用易失性布尔变量忙于等待
- 具有易失性原子变量的原子操作
- 如果我锁定变量,我是否必须将复杂类型标记为“易失性”?
- 为什么这个易失性变量的地址总是在1
- c++编译器能否消除未读的易失性局部变量?
- 在C中递增一个易失性变量
- GCC可以使用读-修改-写指令来更新易失性变量吗?
- 对 WinAPI 线程之间的共享变量使用易失性