赋值对于 C11 原子意味着什么?

问题描述 投票:0回答:1

例如,

atomic_int test(void)
{
  atomic_int tmp = ATOMIC_VAR_INIT(14);
  tmp = 47;                    // Looks like atomic_store
  atomic_int mc;               // Probably just uninitialised data
  memcpy(&mc,&tmp,sizeof(mc)); // Probably equivalent to a copy
  tmp = mc + 4;                // Arithmetic
  return tmp;                  // A copy - perhaps load then store
}

Clang 对这一切很满意。我已经阅读了标准的第 7.17 节,它说了很多关于内存模型和定义的函数(init、store、load 等)的内容,但没有提及任何关于常用操作(+、= 等)的内容。

同样有趣的是将

struct wot { atomic_int value; }
传递给函数的行为。

我愿意相信赋值的行为与原子加载相同,然后使用 memory_order_seq_cst 进行存储。

更乐观的是,我愿意相信结构体赋值、传递给函数、从函数返回甚至 memcpy 的行为也与在 memory_order_seq_cst 下仔细复制位模式相同。

不过,我找不到任何支持该标准信念的证据。原子原语的赋值和 memcpy 肯定有可能是未定义的行为。

原子基元上的基元操作应该如何表现?

谢谢!

atomic c11
1个回答
3
投票

_Atomic
限定的对象的操作(
atomic_int
只是不同的写法)保证具有顺序一致性。您会发现每个操作数的语义部分末尾都提到了这一点。 (也许缺少提及作业。)

您的代码在两个地方不正确:初始化必须使用

ATOMIC_VAR_INIT
宏(7.17.2.1),并且
memcpy
未定义(大小可能不一致),尽管它可能适用于大多数架构。

还有线路

tmp = mc + 4;                // Arithmetic

不符合您的评论所述。这不是对原子对象进行算术运算,而是加载后进行普通加法。更有趣的是

mc += 4;                // Arithmetic

这是一个具有顺序一致性的原子操作。来自 C11 标准第 6.5.16.2 节:

E1

op = E2 形式的 A 复合赋值 等价于简单赋值表达式 E1 = E1 op (E2),除了左值 E1 仅计算一次,并且相对于不确定序列函数调用时,复合赋值操作是单次求值。 如果 E1 具有原子类型,则复合赋值是具有

memory_order_seq_cst
内存顺序语义的读-修改-写操作。

© www.soinside.com 2019 - 2024. All rights reserved.