将 _Atomic(type) 转换为 type

Converting _Atomic(type) to type

提问人:konsolas 提问时间:9/3/2023 更新时间:9/3/2023 访问量:71

问:

请考虑以下 C 代码:

#include <stdatomic.h>

struct _opaque;
typedef struct _opaque *opaque;
struct container { _Atomic opaque x; };

struct container get_container();
void consume_opaque(opaque);

void test() {
    consume_opaque(get_container().x);
}

这无法编译 (Clang 16),并出现以下错误:

error: passing '_Atomic(opaque)' to parameter of incompatible type 'opaque' (aka 'struct _opaque *')

此代码仍然无法编译,即使在尝试显式转换参数后也是如此: 。(opaque) get_container().x

相比之下,请考虑以下几点:

#include <stdatomic.h>

struct _opaque;
typedef struct _opaque *opaque;
struct container { _Atomic opaque x; };

struct container *get_container();
void consume_opaque(opaque);

void test() {
    consume_opaque(get_container()->x);
}

这编译得非常好,编译器显然很乐意转换,但在容器按值返回的情况下则不然。get_container()->xget_container().x

为什么会这样?如何让编译器在第一个示例中进行转换,而不显式保存返回值到局部变量?get_container()

c 铸造 原子

评论

2赞 Peter Cordes 9/3/2023
GCC13 编译它时没有任何警告: godbolt.org/z/s3oT7PMdx .但请注意,asm 只用寄存器进行成员的左值到右值的转换,而不是从内存中加载原子。因为该对象仅作为本地临时返回值存在。在 C 中,复制整个结构不尊重其成员之类的东西,因此您设法绕过了通常阻止您复制原子对象的事情(例如在 C++ 中没有复制构造函数)。_Atomic opaque xmov rdi, rax_Atomicvolatile_Atomicstd::atomic
0赞 Andrew Henle 9/3/2023
教你编写代码的人,显然不知道在文件范围内以下划线开头的标识符是保留的:“所有以下划线开头的标识符始终保留为在普通和标记命名空间中用作具有文件范围的标识符。struct _opaque
0赞 konsolas 9/4/2023
@PeterCordes我很想知道 GCC 或 Clang 接受/拒绝此代码是否正确,就标准而言 - 我找不到任何暗示无法复制_Atomic类型的东西。这似乎意味着两者之一存在错误。
1赞 konsolas 9/4/2023
@AndrewHenle谢谢你让我知道。对于将来我编写的任何代码,我都会牢记这一点。

答: 暂无答案