2
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 相关的一些额外周期,对吗?

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

提前致谢

4

2 回答 2

1

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

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

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

于 2012-09-25T17:35:17.703 回答
0

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

于 2012-09-25T17:04:20.257 回答