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

Volatile Pointer to Non Volatile Data

假设我有以下声明:

int* volatile x;

我相信这定义了一个可变指针 "normal" 变量。

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

初猜

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

对我来说这似乎毫无用处,我会假设这不是真正的操作。

第二次猜想

指针可以改变,因此如果指针改变,编译器必须在使用之前重新加载指针中的值。但是如果它验证指针没有改变(通过附加检查),它就可以假设它指向的值也保持不变。

所以我的问题是:

声明指向非易失性数据的易失性指针实际上有什么作用?

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

每当访问指针时,volatile 限定符保证从内存中重新读取它的值(指针的值)。

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


[编辑]为了解决@DavidSchwartz的评论,我应该注意到“从内存中重新读取”是一个(不精确,但AFAIK常用)shorthand用于“好像是从抽象机的内存中重新读取的".

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

An object that has volatile-qualified type may be modified in ways unknown to the implementation or have other unknown side effects. Therefore any expression referring to such an object shall be evaluated strictly according to the rules of the abstract machine, as described in 5.1.2.3. Furthermore, at every sequence point the value last stored in the object shall agree with that prescribed by the abstract machine, except as modified by the unknown factors mentioned previously (134). What constitutes an access to an object that has volatile-qualified type is implementation-defined.

同一草案有 6.5.16/3 的脚注(赋值运算符):

The implementation is permitted to read the object to determine the value but is not required to, even when the object has volatile-qualified type

所以最后 volatile 并不 需要 物理内存读取,但兼容实现的可观察行为必须 就好像 无论如何都做了一个。

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

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