非易失性数据的易失性指针

假设我有以下声明:

int* volatile x; 

我相信这定义了一个易失性指针“正常”变量。

对我来说,这可能意味着两件事之一:

首先猜猜

指针可以更改,但数字不会更改,恕不另行通知。 这意味着一些其他线程(编译器不知道)可以更改指针,但如果旧指针指向“12”则新指针(指针的新值,因为线程更改它) )会指向另一个“12”。

对我来说这似乎没用,我认为这不是真正的操作。

第二个猜猜

指针可以更改,因此如果指针发生更改,编译器必须在使用之前重新加载指针中的值。 但是如果它确认指针没有改变(带有附加检查),那么它可以假设它指向的值也保持不变。

所以我的问题是:

声明指向非易失性数据的易失性指针实际上做了什么?

int *volatile x; 声明一个指向非易失性int的volatile指针。

无论何时访问指针, volatile限定符都保证从内存中重新读取其值(指针的值)。

由于指向的int是非易失性的,因此允许编译器在指针的当前值指向的地址处重用先前缓存的值。 从技术上讲,只要存在最初从当前地址检索的缓存值,无论指针是否已更改,都允许这样做。


[编辑]为了解决@DavidSchwartz的评论,我应该注意“ 重读内存 ”是一种(不是迂回精确,但AFAIK常用的)简写,“ 好像它是从抽象机器的内存中重新读取的 ”。

例如, C11草案N1570 6.7.3 / 7说:

具有volatile限定类型的对象可能以实现未知的方式进行修改,或者具有其他未知的副作用。 因此,任何涉及这种对象的表达都应严格按照抽象机的规则进行评估,如5.1.2.3所述。 此外,在每个序列点,最后存储在对象中的值应与抽象机器规定的值一致,除非由前面提到的未知因素修改(134)。 什么构成对具有volatile限定类型的对象的访问是实现定义的。

相同的草案有6.5.16 / 3(指派运营商)的脚注:

允许实现读取对象以确定值但不是必需的,即使对象具有volatile-quali fi ed类型

因此,最后volatile 不需要物理内存读取,但是兼容实现的可观察行为必须仿佛无论如何都要做。

volatile表示指针的值(即它指向的内存位置)可以改变; 因此,编译器必须确保各种高速缓存对于该指针具有相同的值,或者为每次读取从内存加载指针,并在每次写入时将其写入内存。

然而, volatile没有说明指出的价值。 所以它可以改变,并且可以在不同的线程中具有不同的值。