Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 指向非易失性数据的易失性指针_C++_C_Pointers_Volatile_Non Volatile - Fatal编程技术网

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

C++ 指向非易失性数据的易失性指针,c++,c,pointers,volatile,non-volatile,C++,C,Pointers,Volatile,Non Volatile,假设我有以下声明: int* volatile x; 我相信这定义了一个易失性指针“normal”变量 对我来说,这可能意味着两件事之一: 第一次猜测 指针可以更改,但数字不会在没有通知的情况下更改。这意味着其他线程(编译器不知道)可以更改指针,但是如果旧指针指向“12”,那么新指针(指针的新值,因为线程更改了它)将指向另一个“12” 对我来说,这似乎是相当无用的,我认为这不是真正的操作 第二次猜测 指针可以更改,因此如果指针更改,编译器必须在使用指针之前重新加载指针中的值。但是,如果它验证指

假设我有以下声明:

int* volatile x;
我相信这定义了一个易失性指针“normal”变量

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

第一次猜测

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

对我来说,这似乎是相当无用的,我认为这不是真正的操作

第二次猜测

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

所以我的问题是:


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

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

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


[编辑]为了回应@DavidSchwartz的评论,我应该指出,“从内存中重新读取”是一个(不是学究式的精确,但通常使用的)简写,表示“好像它是从抽象机器中的内存中重新读取的”

例如,
C11
草案N1570 6.7.3/7规定:

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

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

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


因此,最终,
volatile
不需要物理内存读取,但兼容实现的可观察行为必须与执行时的行为相同。

int*volatile x声明指向非易失性int的易失性指针

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

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


[编辑]为了回应@DavidSchwartz的评论,我应该指出,“从内存中重新读取”是一个(不是学究式的精确,但通常使用的)简写,表示“好像它是从抽象机器中的内存中重新读取的”

例如,
C11
草案N1570 6.7.3/7规定:

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

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

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


因此,最终,
volatile
不需要物理内存读取,但兼容实现的可观察行为必须与执行时一样。

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


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

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


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

volatile说明符与线程无关。
volatile
只是表示“它可以观察到的读取线程的行为”