1

假设我有以下声明:

int* volatile x;

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

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

第一个猜测

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

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

第二个猜测

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

所以我的问题是:

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

4

2 回答 2

2

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

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

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


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

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

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

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

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

所以最终volatile不需要物理内存读取,但兼容实现的可观察行为必须是无论如何做出来的。

于 2016-08-04T23:30:08.840 回答
-2

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

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

于 2016-08-04T23:34:14.250 回答