我正在查看以下代码:
inline void* interlocked_read_acquire(void* volatile* x);
我想知道为什么不只是volatile void*
作为一个论点。一般来说, a 的语义或定义是volatile*
什么?我还假设您可以将volatile*
限定符与除 void 之外的任何其他类型一起使用。那是对的吗?
我正在查看以下代码:
inline void* interlocked_read_acquire(void* volatile* x);
我想知道为什么不只是volatile void*
作为一个论点。一般来说, a 的语义或定义是volatile*
什么?我还假设您可以将volatile*
限定符与除 void 之外的任何其他类型一起使用。那是对的吗?
想知道为什么 [
void* volatile*
and] 不只是volatile void*
...?
它们是不同的东西。
void* volatile*
是一个指向 volatile ( void*
) 的指针(因此可以在不强制转换的情况下取消引用和访问volatile void*
,但只会给你一些内存中尚未指定的东西的地址)
volatile void*
是指向 volatile 的指针void
(因此您必须强制转换为 sayvolatile int*
或volatile My_Class*
取消引用之前的类型)
void * ptr1;
表示这ptr1
是一个类型为 的变量void *
。这种类型表示一个“通用指针”——它指向某个内存位置,但不包含该位置的类型信息。
void * volatile ptr2;
表示该变量ptr2
也是一个泛型指针,但ptr2
也是volatile
. 该关键字volatile
称为cv 限定符,它的语法规则与const
.
volatile 变量的含义是当其他一些代码说ptr2
时,编译器无法优化它;它必须读取或写入存储的内存位置ptr2
;它必须考虑到某些外部进程也在读取或写入该位置的可能性。
最后,void * volatile *x
是可以指向的东西ptr2
。例如我们可以有void * volatile * x = &ptr2;
. *x = NULL;
例如,如果我们接着写, then*x
的类型void * volatile
与我们刚刚看到的 for 具有相同的含义ptr2
。
如果您省略了限定符,编译器会抱怨,例如void * *y = &ptr2;
. 这是因为表达式*y
将具有类型void *
(非易失性),因此编译器可能会围绕它执行优化,但这是不正确的行为,因为ptr2
不允许这些优化。(您可能会认识到“volatile-correctness”与 const-correctness 是同一类东西)。
volatile 是一个附加属性,您可以先将其删除以读取
void* volatile* x
至:
void* *x
这很熟悉。例如,一个 malloc-ed 内存指针数组。你不会混淆
volatile void*
这减少到
void* x.