将 volatile 分配给非易失性语义和 C 标准

aia*_*iao 4 c volatile language-lawyer non-volatile

volatile int vfoo = 0;
void func()
{
    int bar;
    do
    {
        bar = vfoo;  // L.7
    }while(bar!=1);
    return;
}
Run Code Online (Sandbox Code Playgroud)

此代码忙等待变量变为1。如果第一遍vfoo未设置为1,我会卡在里面吗。

这段代码编译时没有警告。标准对此有何看法?

  • vfoo被声明为volatile. 因此,读这个变量应该进行优化。
  • 但是,酒吧没有 volatile资格。是否允许编译器优化写入bar?.ie 编译器将对 进行读取访问vfoo,并允许丢弃此值而不将其分配给bar(在 L.7)。
  • 如果这是标准有话要说的特殊情况,能否请您包括该条款并解释标准的律师谈话?

R..*_*R.. 5

标准对此的规定包括:

5.1.2.3 程序执行

¶2 访问易失性对象、修改对象、修改文件或调用执行任何这些操作的函数都是副作用,它们是执行环境状态的变化。表达式的评估通常包括值计算和副作用的启动。左值表达式的值计算包括确定指定对象的身份。

¶4 在抽象机中,所有表达式都按照语义指定的方式进行评估。如果一个实际的实现可以推断出它的值未被使用并且没有产生所需的副作用(包括由调用函数或访问易失性对象引起的任何副作用),则它不需要计算表达式的一部分。

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

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

特别是 ¶2 的要点应该是访问 volatile 对象与调用之类的东西没有什么不同printf——它不能被省略,因为它有副作用。想象一下你的程序bar = vfoo;被替换为bar = printf("hello\n");