这种联合会破坏严格的别名吗?浮点寄存器呢?

Does this union break strict aliasing? What about floating point registers

本文关键字:寄存器 别名 联合会      更新时间:2023-10-16
union
{
    Uint32 Integer;
    Float32 Real;
} Field;    

我必须使用该联合来做一些IEEE技巧,这是否破坏了严格的别名?GCC 没有抛出任何警告(即使使用迂腐的严格混叠也尝试使用 GCC 4.5 和 4.6,但据我所知,GCC 不是很好捕捉严格的混叠规则侵权(大量误报/负(。

Field A;
A.Integer = (Value1 & B) || Value2;
return A.Real;

这是我目前正在使用的片段,它似乎在没有任何警告的情况下正常工作,但某些编译器优化可能会有副作用或未定义的行为。因此,如果该段代码在某些情况下可能不安全,我将努力将其删除。

此外,我假设这段代码需要将数据从大多数现代 CPU 上的标准寄存器移动到浮点寄存器(只是对此感到好奇(,涉及一些相对于旧 CPU 的额外周期,对吗?

上面的代码

并不打算成为优化,所以不要因为滥用优化而贬低我,上面的代码是我获得某个结果的最简单方法(幸运的是,最简单的方法似乎也是我最快的!(,如果结果不安全,那么我将使用较慢的方法。

提前致谢

通过联合的别名在 C 中定义,但在C++中具有未定义的行为;未定义的行为等效于从未初始化的变量读取时发生的行为(左值到右值转换(。

因此,最有可能打破这种情况的方式是优化器决定从联合中消除读取,因为它没有定义的值。 但是,大多数 C 和 C++ 编译器可能会为您提供 C 行为,因为它们无论如何都需要支持它。

值添加别名的安全方法是通过字节复制,例如 std::memcpystd::copy(reinterpret_cast<char *>(...), ...). 或者,如果可以同时使用 C 和 C++ 编译项目,则可以将联合别名代码移动到 C 源文件,并将该代码编译为 C。

它是

UB(但不需要严格的别名(。此外,union d数据始终由实现AFAIK存储在内存中,否则需要知道源数据来自哪个寄存器,这意味着知道源类型。