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

将volatile分配给非volatile语义和C标准,c,language-lawyer,volatile,non-volatile,C,Language Lawyer,Volatile,Non Volatile,此代码忙等待变量变为1。如果第一次通过时vfoo未设置为1,我会被卡在里面 这段代码编译时没有警告。 标准对此有何规定 vfoo声明为volatile。因此,对该变量的读取应该而不是进行优化 但是,bar不合格。是否允许编译器优化对该条的写入。i、 e.编译器将对vfoo进行读取访问,并允许放弃该值,而不将其分配给bar(见L.7) 如果这是一个特殊情况,标准有话要说,你能包括条款并解释标准的律师谈话吗 必须在任何访问上读取volatile变量。在您的代码段中,无法优化读取。编译器知道bar可

此代码忙等待变量变为
1
。如果第一次通过时
vfoo
未设置为
1
,我会被卡在里面

这段代码编译时没有警告。 标准对此有何规定

  • vfoo
    声明为
    volatile
    。因此,对该变量的读取应该而不是进行优化
  • 但是,bar不合格。是否允许编译器优化对该
    条的写入。i、 e.编译器将对
    vfoo
    进行读取访问,并允许放弃该值,而不将其分配给
    bar
    (见L.7)
  • 如果这是一个特殊情况,标准有话要说,你能包括条款并解释标准的律师谈话吗

必须在任何访问上读取volatile变量。在您的代码段中,无法优化读取。编译器知道
bar
可能会受到副作用的影响。因此,将正确检查条件


标准对此的说明包括:

5.1.2.3程序执行

^2访问易失性对象、修改对象、修改文件或调用执行这些操作的函数都是副作用,这些都是执行环境状态的变化。表达式的评估通常包括数值计算和副作用的开始。左值表达式的值计算包括确定指定对象的标识

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

6一致性实施的最低要求是:

  • 对易失性对象的访问严格按照抽象机器的规则进行评估
《2》特别值得一提的是,访问易失性对象与调用
printf
没有什么不同-它不能被忽略,因为它有副作用。想象一下你的程序使用
bar=vfoo替换为
bar=printf(“hello\n”)

但是,
bar
不是限定的

变量
bar
用于保存值。您是否关心存储在其中的值,或者是否关心根据ABI精确表示该变量

我可以保证你是后者。您的程序取决于前者

是否允许编译器优化对此条的写入

当然。为什么您可能会关心读取的值是否真的写入了分配给堆栈上变量的内存位置

您指定的只是将读取的值作为退出条件进行测试:

volatile int vfoo = 0;
void func()
{
    int bar;
    do
    {
        bar = vfoo;  // L.7
    }while(bar!=1);
    return;
}
.即。编译器将对vfoo进行读访问,并允许 放弃该值,不要将其分配给bar(在L.7处)

当然不是

编译器需要保存volatile read获得的值足够长的时间才能将其与1进行比较。但是没有更多的时间了,因为你以后再也不用
bar

可能是一个奇怪的CPU在条件寄存器中作为一个EQ1(“等于1”)标志,每当加载一个等于1的值时就会设置该标志。然后编译器甚至不会临时存储读取值,而只存储EQ1条件测试


根据您的假设编译器可以丢弃所有非易失性变量的变量值,非易失性对象几乎没有可能的用途

这就是gcc的好处吗;或者说标准要求100%的傻瓜式。正如我所写的-它不能优化非易失性变量,因为它也变得容易产生副作用。@P_uj_u_u你能引用C标准吗?“我不是C专家,但C++中的情况会完全不同。”康拉德鲁道夫100%不同意。你能引用C++标准吗?@格尔德:你被引用词弄糊涂了。将从易失性对象加载的值存储到其他地方并不是引用它。您引用的语言是关于通过错误的非易失性类型的覆盖(通过类型双关)对象非法访问易失性对象。例如
*(int*)和vfoo
。它将如何“优化写入
栏的操作”
?为了做到这一点,它写入的值必须事先知道,但该值是加载
vfoo
的结果,不能忽略,因为
vfoo
是易变的。“如果第一次通过vfoo时没有设置为1,我会卡在里面。”如何测试它?1)正确。2)
bar
的类型无关紧要,编译器不允许优化
vfoo
的读取。3) 不,这不是一个特例,而且100%定义良好。“与调用
printf
没有区别”更像是调用
scanf
here@curiousguy:任何一种都有无法忽略的副作用;这就是重点
scanf
是一个更接近于易变负载的语义模拟,但我试图避免语义上的争论,并将重点放在更高层次的“有副作用”概念上。
        bar = ...
    }while(bar!=1);