说,我有这段代码:
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变量有关的不一致行为。
答案 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
和相应的赋值操作。