いくつかの悪いコードが int 値を float アドレスに設定したとしましょう。一般に、その int 値を取得するにはどうすればよいですか?
2 に答える
この回答に関する注意:以下のコードは、を使用して (int
用に予約されたメモリ位置に を格納したというfloat
)問題をエミュレートし、再度reinterpret_cast
を使用して問題を解決しreinterpret_cast
ます。これは、厳密なエイリアシング規則(3.10/10 C++ 標準) を破ります。これは、オブジェクトの実際の型と一致しない型の (g)lvalue を介してオブジェクトにアクセスすることを示しています (ある意味で一致します)。未定義の動作を呼び出します。
このため、以下に示すコードは使用しないでください。解決策、つまり を使用することreinterpret_cast
は、少なくとも危険です (ただし、多くの場合は機能します)。正しい解決策については、Steve Jessop の回答を参照してください。私の間違いを指摘してくれてありがとう(コメントを参照)。
元の回答:
値が格納されているアドレスがあり、そのアドレスが整数アクセス用に正しく配置されている場合、これに使用できるはずですreinterpret_cast
:
int main()
{
/* An integer and an uninitialized float: */
int original = 45;
alignas(int) alignas(float) float f;
float *p = &f;
/* "Erroneously" putting an int into the address of the float: */
*reinterpret_cast<int*>(p) = original;
/* Retrieving the int (this is what you were looking for): */
int retrieved = *reinterpret_cast<int*>(p);
std::cout << "Original: " << original
<< ", Stored float: " << f
<< ", Retrieved: " << retrieved
<< std::endl;
return 0;
}
(上記で使用されているキーワードalignas
は C++11 のものです。コンパイラがそれを受け入れない可能性があります。いずれにせよ、コードのその部分は問題をエミュレートするための私の方法であり、ソリューションの本質的な部分ではありません。)
答えreinterpret_cast<int*>
は厳密なエイリアシングに違反しており、未定義の動作をしています。
定義された動作でそれを行いたい場合:
int read_int_from_float(const float &f) {
int result;
std::memcpy(&result, &f, sizeof(result));
return result;
}
これはそれを確認した後であり、同じサイズfloat
を持っています。int
同じ配置である必要はありません。