【问题标题】:Comparing volatile variable to itself将 volatile 变量与自身进行比较
【发布时间】:2021-12-17 13:46:24
【问题描述】:

编译器能否优化 volatile 变量与自身的比较并假设它相等?或者它必须读取两次这个变量并比较它得到的两个值?

【问题讨论】:

  • 我认为它需要读取两次,因为波动性的事实意味着它可以在任何两次访问之间发生变化。但是我手头没有任何可以给出权威答案的标准。
  • @SornelHaetir 从 C 的角度来看,读取甚至可以改变值。
  • 严格来说,这取决于实现如何定义对 volatile 对象的访问。但是对于“正常”实现是的,编译器需要生成两个读取然后进行比较。该值可以在读取之间发生变化,甚至因为读取。

标签: c optimization compilation volatile


【解决方案1】:

我对 volatile 变量的看法是,读取或写入它们被视为 I/O 函数。

对 I/O 函数的调用永远无法优化,因为它有副作用。也不能优化涉及 volatile 变量的读取或写入。

如果您对同一个输入函数的两次调用进行编码,编译器必须确保输入函数实际上被称为twice,因为它可能会给出不同的结果。同样,您可以从volatile 变量中读取两次,在两次读取之间,其他人可以更改变量的值所以编译器总是会发出指令来读取它两次,而对于非易失性变量,它可以简单地假设它们没有被程序外的任何人修改

同样,I/O 函数调用不能重新排序,易失性变量访问也不能。

【讨论】:

  • 这是查看 volatile 的好方法,它可以回答很多这样的问题。我们确定所有编译器都应该这样做吗?是否符合某些规范?
  • 我认为它是特定于编译器的,可能不适用于所有编译器。
  • 请注意,尽管编译器会生成两次读取,但如果将位置标记为不可缓存,则只会读取两次。如何做到这一点因系统而异。
  • 感谢纠正我。但我知道有些编译器允许您将所有变量隐式声明为 volatile。
【解决方案2】:

C 2018 6.7.3 8 说:

具有 volatile 限定类型的对象可能会以实现未知的方式被修改或具有其他未知的副作用。因此,任何引用[具有 volatile 限定类型的对象] 的表达式都应严格按照抽象机的规则进行评估,如 5.1.2.3 中所述……构成对具有 volatile 限定类型的对象的访问是实现-已定义。

5.1.2.3 4 说:

...在抽象机中,所有表达式都按照语义指定的方式进行评估...

x == x 中,其中x 是一个volatile 限定的对象,其语义是将第一个x 转换为对象x 的值(通过左值转换根据 6.3.2.1 2),将第二个 x 转换为其值,并将两个值进行比较。将对象转换为其值会访问该对象,获取存储在其中的值。

所以抽象机访问x 两次。到6.7.3 8,这个评价是严格的;实际程序必须实现与抽象机相同的访问,所以x的值必须被访问两次;两者都不能被优化掉。

C 标准将其留给 C 实现来定义构成访问的内容。但无论如何,程序必须执行两次。

【讨论】:

    猜你喜欢
    • 2021-06-09
    • 2015-01-24
    • 2013-01-05
    • 1970-01-01
    • 1970-01-01
    • 2017-07-09
    • 1970-01-01
    相关资源
    最近更新 更多