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