当前位置: 首页 > 知识库问答 >
问题:

是否允许编译器对本地volatile进行常量折叠?

阮选
2023-03-14

请考虑以下简单代码:

void g();

void foo()
{
    volatile bool x = false;
    if (x)
        g();
}

https://godbolt.org/z/i2kby7

您可以看到gccclang都没有优化对g的潜在调用。在我的理解中,这是正确的:抽象机器假设volatile变量随时可能发生变化(例如,由于是硬件映射的),因此将false初始化常数折叠为iff检查将是错误的。

>

  • 这里讨论了消除对volatile的读写操作:允许编译器优化本地volatile变量吗?(谢谢内森!)。我认为标准是非常清楚的,那些读写必须发生。但是这些讨论并不包括编译器将读取结果视为理所当然并基于此进行优化是否合法。我想这在标准中是不足/没有规定的,但如果有人证明我错了,我会很高兴的。

    当然,我可以让x成为一个非局部变量来回避这个问题。这个问题更多是出于好奇。

  • 共有1个答案

    屈星腾
    2023-03-14

    我认为[intro.execution](段落号vary)可以用来解释MSVC行为:

    具有自动存储持续时间的每个对象的实例与其块中的每个条目相关联。这样的对象在执行块期间和块挂起期间存在并保留其最后存储的值...

    该标准不允许消除对volatile glvalue的读取,但上面的段落可以解释为允许预测值false

    不清楚C内存/对象模型中是否有一个非显式存储到具有自动存储持续时间的对象中。

     类似资料:
    • 我有一个理论(非确定性,难以测试,从未发生在实践中)硬件问题报告硬件供应商,其中双字写入特定内存范围可能破坏任何未来的总线传输。 虽然我在C代码中没有任何明确的双词写入,但我担心编译器(在当前或未来的实现中)被允许将多个相邻的词赋值合并为单个双词赋值。 编译器不允许对Volatile的赋值进行重新排序,但(对我来说)不清楚合并是否算作重新排序。我的直觉是这样的,但我以前被语言律师纠正过! 示例:

    • 问题内容: 我发现Java支持原始类型的常量折叠,但是s呢? 例 如果我创建以下源代码 编译后的代码有什么内容? 组合版? 还是效率较低的运行时串联版本? 问题答案: 这是一个简单的测试: 输出: 因此,是的,编译器将折叠。

    • IE 可能会失败。 C11附件J.2内容如下

    • 问题内容: 嗨,我遇到过Java编译器使用了称为Constant Folding的东西。这是什么?以及如何影响? 问题答案: 常量折叠是编译器在其中查找包含编译时常量的表达式并将其替换为结果的地方,可有效删除多余的运行时计算。

    • 我在我的Web服务器(Debian/Nginx/Gunicorn)上运行Redis进行会话存储,我有理由相信我的Redis服务器遭到了黑客攻击。这绝对是可能的,因为如果我在另一台机器上针对web服务器运行命令“redis cli-h(HOST IP)”,我就可以进入控制台并运行命令。我有两个问题。首先,如果我在我的iptables文件中添加一个新的部分,如下所示,我会正确地阻止除Web服务器本身之

    • 有问题的代码如下: 编译器会优化它吗?根据C-Standard(如果我理解正确的话),第二个操作数必须提升为;因此乘法必须使用FPU(或fp仿真)完成。 从理论上讲,该操作可以在正常的硬件寄存器中完成,只需添加一个即时的(并且可能是溢出检查)。是否允许编译器执行此优化?是否有已知的编译器这样做?如果是这样,他们是否也会识别该表达式 这是避免有关隐式转换的静态代码检查器警告所必需的? 补充一下:我知