在C++中提及工会成员有多安全?
How safe is it to have references to union members in C++?
>想象一下这种情况:
union Reg16
{
uint16_t word;
struct
{
uint8_t bottom;
uint8_t top;
};
};
假设我在某处有这样的东西,它使用了这个联合:
Reg16 reg_AF;
uint8_t& reg_A = reg_AF.top;
uint8_t& reg_F = reg_AF.bottom;
即使工会在技术上并不总是提到u8,保留对工会各自部分的引用是否安全?我不确定这是否违反了严格的别名规则,但值得注意的是,任何地方都没有引用word
,只有top
和bottom
。特别是在这种特殊情况下,引用应该指向整个 u16 的上半部分和下半部分,所以没有任何 UB,因为我不会通过阅读它们获得任何我不希望获得的价值,而不是如果我有一个浮点数和一个 int 的联合并引用了它们中的每一个。
提前谢谢。
首先要说的是,在严格的别名规则(C++03 标准的第 3.10 节)中有明确的语言†它允许通过unsigned char
访问值。 如果uint8_t
是unsigned char
的typedef,那么这种用法将是明确的合法的。
但是,对于未unsigned char
的实现定义类型,uint8_t
可以是typedef(尽管仔细阅读标准表明,如果uint8_t
存在,则它的大小必须与unsigned char
相同)。 此外,这个问题仍然可以对其他类型的人感兴趣(例如uint32_t
和uint16_t
)。
现有的引用绝对没有害处 - 如果在联合包含word
而不是top
+bottom
时使用引用,则可能会出现唯一的危险。 另一方面,如果发生这种情况(并且top
/bottom
未unsigned char
),则违反了严格的混叠规则。
鉴于 C 标准明确允许通过联合进行类型双关(与 C++ 不同),您的 C++ 编译器也很有可能允许这样做。
旁白:严格来说,这个样本是不合法的;匿名结构是GCC、Clang和MSVC支持的扩展(所以问题是,哪些编译器不支持它们)。
† 在后来的版本中,措辞略有变化,章节编号可能有所变化——但原则保持不变。
假设你的代码实际上是:
union Reg16
{
uint16_t word;
struct
{
uint8_t bottom;
uint8_t top;
} bytes;
};
这作为声明是完全可以的:
Reg16 reg_AF;
uint8_t& reg_A = reg_AF.bytes.top;
uint8_t& reg_F = reg_AF.bytes.bottom;
您可以像直接使用结构成员一样使用引用。
例如,reg_AF.bytes.bottom = 'A'; std::cout << ref_F;
完全没问题:联合当前包含结构,并且您正确使用了对结构成员的引用。
但是这个reg_AF.word = 0x4142; std::cout << reg_A;
和reg_AF.word = 0x4142; std::cout << reg_AF.bytes.bottom;
完全一样是UB(*)
(*) 根据严格的别名规则,您不应访问与用于写入该值的类型不同的类型的值。由于struct bytes
与uint_8
不同,混叠不正确。话虽如此,普通编译器目前接受它作为联合的扩展,甚至可以选择忽略严格的混叠规则。只是代码不符合标准,另一个编译器的行为可能不同。
- 静态 constexpr 类成员变量对多线程读取是否安全?
- 当我在C++中调用 struce 的只读静态成员时,线程是否安全
- 让所有成员都活跃在C++联盟中安全吗
- std::mutex作为一个成员变量对多个线程来说是安全的吗
- 将常量引用成员设置为临时变量是否安全
- c++:成员函数中的"this == nullptr"安全吗?
- 构造函数成员初始值设定项跨成员列出,安全吗?
- 静态类数据成员的线程安全
- 直接向工会而不是其特定成员之一发送memcpy数据是否安全
- 将数据成员的指针传递给基类构造函数是否安全?
- 将 QObject 用作类成员并将该成员用作连接的上下文是否安全?
- 在C++中提及工会成员有多安全?
- 调用不访问已删除对象中的任何类成员的类方法是否安全
- 一个线程设置成员,而另一个循环上方 - 是此螺纹 - 不安全
- 派生类没有额外的数据成员;将基对象静态向下转换为派生对象是否安全
- C#:如何设置不安全结构的成员阵列
- 使用之前在初始值设定项列表中初始化的成员初始化成员是否安全
- 对类成员的双冒号访问(::)是线程安全的
- 编写非虚拟条件成员函数安全吗
- 从c++中的派生类调用未在基类上定义的成员函数是否安全