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

时间:2012-09-06 09:32:14

标签: c++ gcc unions floating strict-aliasing

union
{
    Uint32 Integer;
    Float32 Real;
} Field;    

我必须使用该联盟获得一点IEEE技巧,这是否会打破严格的别名?海湾合作委员会没有发出任何警告(尝试使用GCC 4.5和4.6,即使是迂腐严格的混淆,但据我所知,GCC不是很好地捕捉严格的混叠规则侵权(大量误报/否定)。

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

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

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

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

提前致谢

2 个答案:

答案 0 :(得分:1)

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

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

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

答案 1 :(得分:0)

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