我似乎总体上对volatiles
有一个合理的理解,但有一个看似不明确的情况,我不确定每个标准应该如何工作。我已经阅读了C99的相关部分以及SO上的十几个或更多相关帖子,但无法找到这种情况下的逻辑或解释这种情况的地方。赋值表达式和volatile
假设我们有这样的一段代码:
int a, c;
volatile int b;
a = b = 1;
c = b += 1; /* or equivalently c = ++b; */
应该a
这样的评价:
b = 1;
a = b; // volatile is read
或像这样:
b = 1;
a = 1; // volatile isn't read
?
同样,应该c
这样的评价:
int tmp = b;
tmp++;
b = tmp;
c = b; // volatile is read
或像这样:
int tmp = b;
tmp++;
b = tmp;
c = tmp; // volatile isn't read
?
在简单的情况下,如a = b; c = b;
事情很清楚。但是上面的那些呢?
基本上,问题是,究竟是什么“表达有分配后左操作数的值”是指在C99的6.5.16c3当对象是挥发性?:
赋值运算符商店由左边的操作数指定的对象中的值。一个赋值表达式在赋值之后具有左操作数 的值,但不是左值。
它是否意味着要额外读取volatile以产生赋值表达式的值?
UPDATE:
所以,这里的窘境。
如果未从易失性物体的额外的读获得了“分配后的对象的值”,则编译器作出的假设是,挥发性对象b
:
- 是能够保持任意
int
值写入它,它可能不是(比方说,0位是硬连线到0,这与硬件寄存器,这是不寻常的事情,我们应该使用挥发物) - 不能改变之间的指定写入发生时的时间点和获取表达式值的时间点(并且可能是一个问题与硬件寄存器)
的,因为所有的和,表达值,如果没有从所述易失性物体的额外的读得到,不会产生挥发性物体,其标准权利要求应该是这样的值。
这两个假设似乎都不符合易失物体的性质。
如果OTOH是从所述易失性对象的额外隐含读取中获得“赋值之后的对象的值”,那么评估具有易失性左操作数的赋值表达式的副作用取决于是否使用表达式值或者不是或完全是任意的,这将是一个奇怪的,意想不到的和记录不完善的行为。
我希望赋值给volatile并不意味着在store之后进行读取(无论赋值的值是否在其他地方使用都无关紧要)。这意味着标准对volatile变量的映射硬件寄存器定义为volatile变量(或指向volatile的变量)不会有几乎所有人都依赖的语义。 –
@MichaelBurr好点。 –