从其他 StackOverflow 问题和阅读ISO/IEC 草案 C++ 标准标准的第 9.5.1 节看来,使用联合来执行数据文字reinterpret_cast
是未定义的行为。
考虑下面的代码。0xffff
目标是采用IEEE 754 浮点中的整数值并将其字面解释为一系列位。(二进制转换直观地显示了这是如何完成的。)
#include <iostream>
using namespace std;
union unionType {
int myInt;
float myFloat;
};
int main() {
int i = 0xffff;
unionType u;
u.myInt = i;
cout << "size of int " << sizeof(int) << endl;
cout << "size of float " << sizeof(float) << endl;
cout << "myInt " << u.myInt << endl;
cout << "myFloat " << u.myFloat << endl;
float theFloat = *reinterpret_cast<float*>(&i);
cout << "theFloat " << theFloat << endl;
return 0;
}
这段代码的输出,使用 GCC 和 clang 编译器是预期的。
size of int 4
size of float 4
myInt 65535
myFloat 9.18341e-41
theFloat 9.18341e-41
我的问题是,标准是否真的排除了myFloat
确定性的价值?是否以任何方式使用reinterpret_cast
更好的方法来执行这种类型的转换?
该标准在 §9.5.1 中规定了以下内容:
在一个union中,任何时候最多只能有一个非静态数据成员处于活动状态,即任何时候最多可以有一个非静态数据成员的值存储在一个union中。[...]联合的大小足以包含其最大的非静态数据成员。每个非静态数据成员都被分配,就好像它是结构的唯一成员一样。联合对象的所有非静态数据成员具有相同的地址。
最后一句话,保证所有非静态成员具有相同的地址,似乎表明联合的使用保证与 a 的使用相同reinterpret_cast
,但前面关于活动数据成员的声明似乎排除了这种保证。
那么哪个结构更正确呢?
编辑:
使用英特尔的icpc
编译器,上面的代码会产生更有趣的结果:
$ icpc union.cpp
$ ./a.out
size of int 4
size of float 4
myInt 65535
myFloat 0
theFloat 0