PAYATHON 2026

C23 之前,原子对象的复合赋值是否保证原子性?

数据阿明

结论

在 C23 之前的标准中,只要编译器正确实现相应 C 标准所支持的原子类型,原子对象上的复合赋值就保证是原子操作,且采用 memory_order_seq_cst 内存顺序。C23 删除了那条与此相冲突的注释,但原子性保证并非从 C23 才开始。

标准条文如何协调

问题中的两段文字乍看有矛盾:N3047 §7.17.7.5 p5 的注释称,op= 不保证原子执行;§6.5.16.2 p4 则明确规定,若 E1 是原子类型,复合赋值就是具有 memory_order_seq_cst 语义的 read-modify-write 操作。

应以 §6.5.16.2 p4 的规范性要求为准。§7.17.7.5 p5 是注释。根据题目给出的材料,DR 486 引用了这条注释,N2389(1.3)指出其中的说法有误,C23 随后将其删除。因此,这条注释不能推翻复合赋值条款中的规范性保证。

示例

#include <stdatomic.h>

atomic_int counter = 0;

void increment(void) {
    counter += 1;
}

在支持该原子类型且符合相应 C 标准的实现中,counter += 1 是原子的 read-modify-write 操作,内存顺序为 memory_order_seq_cst。复合赋值表达式产生更新后的值,而 atomic_fetch_add(&counter, 1) 返回操作前的值。

旧版编译器需要注意什么

使用旧编译器或选择 C23 之前的语言模式,不会改变标准对符合实现的要求。不过,标准规定了要求,并不能据此断定某个具体编译器没有实现缺陷。若目标编译器对原子类型的支持不完整,或存在不符合标准的行为,应核对其文档和已知问题。标准保证不等于所有旧版编译器的实际行为都符合要求。

备注:内容仅供参考。