C++ C/C++;内存模型允许原子在相同字节中具有不同的粒度?
假设我有以下类型:C++ C/C++;内存模型允许原子在相同字节中具有不同的粒度?,c++,c,language-lawyer,C++,C,Language Lawyer,假设我有以下类型: struct{ int32高; int32低; }; 是否定义了对所有x、&x->high和&x->low(假设U*x)执行原子访问(例如使用atomic\U load、atomic\U fetch\U add)的行为 我的理解是,C/C++内存模型是使用单个位置的历史记录定义的(以适应较弱的内存体系结构)。如果访问可以跨位置,这是否意味着跨位置同步?如果是这种情况,那么我假设这意味着历史记录基本上是每个字节的,访问int就像在底层4(或8)字节之间同步一样 编辑:修改示例
struct{
int32高;
int32低;
};
是否定义了对所有x
、&x->high
和&x->low
(假设U*x
)执行原子访问(例如使用atomic\U load
、atomic\U fetch\U add
)的行为
我的理解是,C/C++内存模型是使用单个位置的历史记录定义的(以适应较弱的内存体系结构)。如果访问可以跨位置,这是否意味着跨位置同步?如果是这种情况,那么我假设这意味着历史记录基本上是每个字节的,访问int
就像在底层4(或8)字节之间同步一样
编辑:修改示例以避免联合,因为问题的主要部分是关于并发模型的
编辑:修改为使用标准原子,从
stdatomic.h
加载非活动的联盟成员会产生一个不确定的值,无论是否使用\uuu原子加载
进行加载。对于C11/C18(我不能谈论C++)标准原子加载
的函数仅定义为采用\u原子的
限定参数。因此,要对结构T的字段执行atomic_xxx()
操作,您需要:
struct T {
_Atomic int32 high;
_Atomic int32 low;
} ;
struct T foo, bar ;
然后你就可以做(例如)atomic\u fetch\u add(&foo->high,42)
。但是bar=atomic\u load(&foo)
将是未定义的
相反,您可以:
struct T {
int32 high;
int32 low;
} ;
_Atomic struct T foo ;
struct T bar ;
现在定义了bar=atomic_load(&foo)
。但是对foo
中任何单个字段的访问都是未定义的——不管它是否是\u原子的
按照标准,\u原子xxxx
对象应被视为与“普通”xxxx
对象完全不同——它们可能具有不同的大小、表示和对齐方式。因此,将一个xxxx
转换为一个\u原子xxxx
并不比将一个struct
转换为另一个不同的struct
更明智
但是对于gcc和
\uuuuu atomic\uxxx()
内置,您可以执行处理器支持的任何操作。事实上,对于gcc(否则)标准atomic_xxx()
将接受非\u atomic
限定类型的参数,并映射到内置类型。另一方面,clang将非\u原子的限定类型传递给标准函数视为错误。我想澄清一下,这是gcc的
中的一个bug,你不是在问类型双关吗?因为C++中不允许这样做。不确定语言问题是否应该询问非标准函数,如<代码>、μ原子、xxx < /代码>。这些是我知道的唯一的原子操作的原语。原子操作是否有标准函数?原子操作是否有标准函数?
和。(双代码< >代码>建议)是GNU扩展。C和C++内存模型不允许原子函数在某种意义上。它们有原子类型,您可以对其执行原子操作。