InterlockedCompareExchangePointer类型是否错误?需改用InterlockedCompareExchange[64]吗?
这个问题确实戳中了很多人对Interlocked函数和volatile修饰符的理解误区,咱们来逐一理清:
1. 先明确函数签名的真实含义
Windows平台下InterlockedCompareExchangePointer的原型是:
PVOID InterlockedCompareExchangePointer(volatile PVOID *Destination, PVOID Exchange, PVOID Comparand);
这里容易混淆的是volatile PVOID *的含义:它表示指向volatile类型指针的指针吗?不,准确来说是指向volatile PVOID数据的指针——换句话说,Destination是一个指针,它指向的目标(也就是我们要原子交换的那个指针变量)是volatile的,这正是我们需要的行为:因为要原子修改的指针变量本身需要被标记为volatile,防止编译器优化掉对它的读写操作。
如果你有一个需要原子操作的指针变量,正确的声明方式是:
volatile PVOID my_target_ptr;
然后传入&my_target_ptr作为Destination,这时候&my_target_ptr的类型正好是volatile PVOID *,完全匹配函数参数,不存在类型错误。
2. 要不要手动切换到InterlockedCompareExchange[64]?
其实不用。InterlockedCompareExchangePointer本身就是一个平台适配的宏:
- 在32位系统上,它会映射到
InterlockedCompareExchange - 在64位系统上,会自动映射到
InterlockedCompareExchange64
Windows SDK已经帮我们处理了平台差异,不需要自己写#ifdef来区分场景,除非你有非常特殊的自定义需求。
3. 你的理解误区在哪里?
核心误区是混淆了volatile指针和指向volatile数据的指针:
PVOID volatile *:这是指针本身是volatile的(指针的地址不能被优化)volatile PVOID *:这是指针指向的数据是volatile的(也就是我们要修改的指针变量本身是volatile的)
而InterlockedCompareExchangePointer的设计目标是原子修改指针变量的值,所以需要保证这个变量不会被编译器优化,因此要求它是volatile的——函数参数的volatile PVOID *正好对应了这个需求,所以设计是正确的。
内容的提问来源于stack exchange,提问作者Joseph

