我似乎总体上对volatiles有一个合理的理解,但是有一个看似晦涩的情况,在这种情况下,我不确定按照标准该如何工作。我已经阅读了C99的相关部分以及关于SO的十几篇或更多相关文章,但是找不到这种情况下的逻辑或解释这种情况的地方。

假设我们有这段代码:

  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 :

所以,这就是两难境地。

如果从 Volatile 对象的额外读取中未获得“赋值后对象的值”,则编译器将假定 Volatile 对象b:
  • 能够保存写入其中的任意int值,但可能不是(例如,位0硬接线为0,这在硬件寄存器中并不常见,我们应该使用volatiles)
  • 不能在发生分配写操作的时间点与获得表达式值的时间点之间改变(这又可能是硬件寄存器的问题)

  • 并且由于所有这些,如果不从对 Volatile 对象的额外读取中获得表达式值,则不会产生 Volatile 对象的值,标准要求是这种情况。

    这两个假设似乎都不适合 Volatile 对象的性质。

    如果OTOH从额外的隐式读取 Volatile 对象中获得“赋值后对象的值”,则评估具有 Volatile 左操作数的赋值表达式的副作用取决于是否使用表达式值完全武断,这将是一种奇怪,出乎意料且记录不充分的行为。

    最佳答案

    C11澄清这是 undefined 的。

    您可以找到C11 here的最终草案。您引用的第二句话现在引用脚注111:

    赋值运算符将一个值存储在由左操作数指定的对象中。赋值表达式具有赋值后的左操作数的值(111),但不是左值。

    脚注111表示:

    111)允许实现读取对象以确定值,但即使对象具有volatile限定类型,也不需要这样做。

    关于c - 赋值表达式和volatile,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12666916/

    10-14 18:14