C/C++ 内存模型是否允许相同字节的不同粒度的原子?

Does the C/C++ memory model allow atomics at different granularities for the same bytes?

假设我有以下类型:

struct T {
  int32 high;
  int32 low;
};

是否定义了对所有 x&x->high&x->low 执行原子访问(例如使用 atomic_loadatomic_fetch_add)的行为(假设 U* x)?

我的理解是 C/C++ 内存模型是使用多个单独位置的历史定义的(以适应弱内存架构)。如果访问可以跨位置,这是否意味着跨位置同步?如果是这种情况,那么我假设这意味着历史本质上是按字节计算的,访问 int 就像在底层 4(或 8)字节之间进行同步。

edit: 修改示例以避免合并,因为问题的主要部分是关于并发模型的。

edit:修改为使用 stdatomic.h

中的标准原子

无论是否使用 __atomic_load 加载非活动联合成员都会产生不确定的值。

对于 C11/C18(我不能谈论 C++)标准 atomic_xxx() <stdatomic.h> 的函数仅定义为采用 _Atomic 限定参数。因此,要对 struct T 的字段进行 atomic_xxx() 操作,您需要:

struct T {
  _Atomic int32 high;
  _Atomic int32 low;
} ;

struct T foo, bar ;

然后你就可以做到(例如)atomic_fetch_add(&foo->high, 42)。但是 bar = atomic_load(&foo) 将是未定义的。

相反,您可以:

struct T {
  int32 high;
  int32 low;
} ;

_Atomic struct T foo ;
        struct T bar ;

现在 bar = atomic_load(&foo) 已定义。但是对 foo 中任何单个字段的访问是未定义的——无论它是否是 _Atomic.

按照标准,_Atomic xxxx 对象应该被认为与 "ordinary" xxxx 对象完全不同——它们可能具有不同的大小、表示和对齐方式。因此,投射一个 xxxx to/from 一个 _Atomic xxxx 并不比投射一个 struct to/from 另一个不同的 struct.[=33 更明智=]

但是,对于 gcc 和 __atomic_xxx() 内置函数,您可以做任何处理器支持的事情。实际上,对于 gcc,(否则)标准 atomic_xxx() 将接受 not_Atomic 合格类型的参数,并映射到内置参数。另一方面,clang 将 not _Atomic 限定类型传递给标准函数视为错误。恕我直言,这是 gcc <stdatomic.h>.

中的错误