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相关的一些额外周期,对吗?
上面的代码并不是一个优化,所以不要因为滥用优化而贬低我,上面的代码是我获得某个结果的最简单的方法(幸运的是,在我的例子中,最简单的方法似乎也是最快的!),如果结果不安全,那么我将使用较慢的方法。
提前感谢
发布于 2012-09-25 17:35:18
通过联合的别名在C中定义,但在C++中具有未定义的行为;未定义的行为等同于从未初始化的变量读取时发生的行为(左值到右值的转换)。
因此,最有可能破坏这一点的方式是优化器决定从联合中删除读取,因为它没有定义的值。然而,大多数C-and-C++编译器可能会给你提供C行为,因为他们无论如何都需要支持C行为。
为值添加别名的安全方法是通过按字节复制,例如std::memcpy
或std::copy(reinterpret_cast<char *>(...), ...)
。或者,如果您可以用C和C++编译项目,则可以将联合别名代码移动到C源文件中,然后将该代码编译为C。
发布于 2012-09-25 17:04:20
它是UB (但不需要严格的别名)。此外,union
d数据总是通过实现存储在内存中,否则将需要知道源数据来自哪个寄存器,这意味着知道源类型。
https://stackoverflow.com/questions/12297049
复制相似问题