他の StackOverflow の質問や、 ISO/IEC ドラフト C++ 標準規格の§9.5.1を読むと、共用体を使用してデータのリテラルを実行することreinterpret_cast
は未定義の動作であることがわかります。
以下のコードを検討してください。目標は、整数値を取得し、0xffff
それを IEEE 754 浮動小数点の一連のビットとして文字通り解釈することです。( Binary convert は、これがどのように行われるかを視覚的に示しています。 )
#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 で次のように述べています。
共用体では、非静的データ メンバーの最大 1 つがいつでもアクティブになることができます。つまり、非静的データ メンバーの最大 1 つの値をいつでも共用体に格納できます。[...] ユニオンのサイズは、最大の非静的データ メンバーを格納するのに十分です。各非静的データ メンバーは、構造体の唯一のメンバーであるかのように割り当てられます。ユニオン オブジェクトのすべての非静的データ メンバーは、同じアドレスを持ちます。
すべての非静的メンバーが同じアドレスを持つことを保証する最後の文は、共用体の使用が aの使用と同一であることが保証さreinterpret_cast
れていることを示しているようですが、アクティブなデータ メンバーに関する前のステートメントは、この保証を排除しているようです。
では、どちらの構文がより正しいでしょうか?
編集:
Intel のicpc
コンパイラを使用すると、上記のコードはさらに興味深い結果を生成します。
$ icpc union.cpp
$ ./a.out
size of int 4
size of float 4
myInt 65535
myFloat 0
theFloat 0