C语言 “(void)0”在__类型__中有什么用?

o8x7eapl  于 2022-12-17  发布在  其他
关注(0)|答案(1)|浏览(345)

我目前正在ubuntulinux中查看stdatomic.h头文件。
(void)0和逗号在__typeof__ ((void)0, *__atomic_store_ptr)中有什么用?
这不需要什么吗?

#define atomic_store_explicit(PTR, VAL, MO)             \
  __extension__                             \
  ({                                    \
    __auto_type __atomic_store_ptr = (PTR);             \
    __typeof__ ((void)0, *__atomic_store_ptr) __atomic_store_tmp = (VAL);   \
    __atomic_store (__atomic_store_ptr, &__atomic_store_tmp, (MO)); \
  })
cwtwac6a

cwtwac6a1#

PTR恰好是一个数组或函数的指针,或者是一个限定类型的指针时,它会有帮助。((void)0,x)中的逗号操作符将强制进行L值转换。它基本上意味着将一个对象转换为一个值。在数组的情况下,它将数组转换为指向其第一个元素的指针。转换为函数指针的函数。限定类型失去了volatileconst_Atomic等限定符。
除了地址运算符&sizeof_Alignof和gcc的__typeof__typeof将在即将到来的C23中出现)之外,几乎所有情况下都会发生左值转换。
正如评论中所说的,强制转换为void用于消除有关0未使用值的警告。
1.数组指针
参见:

int arr[3];
int (*ptr)[3];

atomic_store_explicit(ptr, &arr, XXX);

如果未强制进行L值转换,则宏将展开为:

__auto_type __atomic_store_ptr = (ptr);

也就是

int (*__atomic_store_ptr)(ptr);

以及

__typeof__ (*__atomic_store_ptr) __atomic_store_tmp = (VAL);

其变为:

int __atomic_store_tmp[3] = arr;

因为解引用int(*)[3]产生int[3]
由于使用指针初始化数组,这将导致编译失败。
使用这个技巧,上面的代码将变成:

int *__atomic_store_tmp = arr;

因为int[3]通过进行L值转换而被变换为int*
1.函数指针。
对于函数指针,情况类似于指向数组的指针。

void foo(void);
void (*ptr)(void);

atomic_store_explicit(ptr, foo, X);

扩展至:

...
__auto_type __atomic_store_ptr = (PTR);

==>

void (*__atomic_store_ptr)(void) = ptr;

以及

__typeof__ (*__atomic_store_ptr) __atomic_store_tmp = (VAL);

==>

void __atomic_store_tmp(void) = foo;

因为取消引用(void(*)(void)会生成函数类型void(void)。由于C中不允许使用初始化函数,因此编译失败。
利用这个技巧,上面的声明变成:

void (*__atomic_store_tmp)(void) = foo;

它编译良好。
1.指向限定类型的指针。
假设:

volatile int *ptr;
atomic_store_explicit(ptr, 42, XXX);

现在:

__auto_type __atomic_store_ptr = (ptr);

==>

volatile int *__atomic_store_ptr = ptr;

以及:

__typeof__ (*__atomic_store_ptr) __atomic_store_tmp = (val);

==>

volatile int __atomic_store_tmp = val;

现在该值变为volatile,导致性能下降等细微问题。使用左值转换时,__atomic_store_tmp的类型变为非限定int

相关问题