我似乎对一般情况有一个合理的理解volatiles,但有一个看似晦涩的案例,我不确定按照标准应该如何工作。我已经阅读了 C99 的相关部分以及关于 SO 的十几个或更多相关帖子,但找不到这种情况下的逻辑或解释这种情况的地方。
假设我们有这样一段代码:
int a, c;
volatile int b;
a = b = 1;
c = b += 1; /* or equivalently c = ++b; */
Run Code Online (Sandbox Code Playgroud)
应该a这样评价:
b = 1;
a = b; // volatile is read
Run Code Online (Sandbox Code Playgroud)
或者像这样:
b = 1;
a = 1; // volatile isn't read
Run Code Online (Sandbox Code Playgroud)
?
同样,应该c这样评估:
int tmp = b;
tmp++;
b = tmp;
c = b; // volatile is read
Run Code Online (Sandbox Code Playgroud)
或者像这样:
int tmp = b;
tmp++;
b = tmp;
c = tmp; // volatile isn't read
Run Code Online (Sandbox Code Playgroud)
?
在简单的情况下,a = b; c = b;事情就很清楚了。但是上面的那些呢?
基本上,问题是,当对象是 volatile 时,C99 的 6.5.16c3 中“表达式具有赋值后左操作数的值”究竟是什么意思?:
赋值运算符在左操作数指定的对象中存储一个值。赋值表达式具有赋值后左操作数的值,但不是左值。
它是否意味着额外读取 volatile 以生成赋值表达式的值?
更新:
所以,这就是困境。
如果“赋值后对象的值”不是从 volatile 对象的额外读取中获得的,那么编译器会假设 volatile 对象b:
int写入其中的任意值,它可能不是(例如,位 0 被硬连接到 0,这对于硬件寄存器来说并不罕见,我们应该使用 volatiles)由于所有这些,如果不是从 volatile 对象的额外读取中获得的表达式值,则不会产生 volatile 对象的值,标准声称应该是这种情况。
这两个假设似乎都不太适合易失性对象的性质。
如果,OTOH,“赋值后对象的值”是从所述易失性对象的额外隐含读取中获得的,那么使用易失性左操作数评估赋值表达式的副作用取决于是否使用了表达式值完全任意的,这将是一种奇怪的、意外的和记录不足的行为。
| 归档时间: |
|
| 查看次数: |
1616 次 |
| 最近记录: |