私はこの関数が何をしているのか、それがなぜ有用であるのか不思議です。私はこれが浮動小数点型の整数型への型変換を行うことを知っています。詳細な説明は感謝します。アドレス浮動小数点型からint型への型変換
unsigned int func(float t)
{
return *(unsigned int *)&t;
}
おかげ
私はこの関数が何をしているのか、それがなぜ有用であるのか不思議です。私はこれが浮動小数点型の整数型への型変換を行うことを知っています。詳細な説明は感謝します。アドレス浮動小数点型からint型への型変換
unsigned int func(float t)
{
return *(unsigned int *)&t;
}
おかげ
それは、そのバイナリ表現所与float
のバイナリ表現と同じであるunsigned integer
を返します。
uint_var = func(float_var);
が本質的に等価である:
memcpy(&uint_var, &float_var, sizeof(uint_var));
このような種類のパンニングも未定義の動作になるので、このようなコードは、携帯型ではありません。ただし、コンパイラのインプリメンテーション依存動作が分かっている低レベルプログラミングでは珍しくありません。
float
これは未定義の動作です。 – EOF
@EOF - 技術的にはそうですが、システムプログラミングと組み込みプログラミングでは一般的な方法ですが、この手法には妥当な選択肢がありません。 – phonetagger
@ EOF私はそれについて何かを加えました。 – Barmar
を仮定するとunsigned int
は同じサイズであり、それは供給float
として(ビットの根底にある)同じバイナリ表現を用いて表されるunsigned int
値を与えます。
呼び出し元は、返された値にビット単位の演算を適用し、個々のビット(符号ビット、指数部と仮数を構成するビットなど)に個別にアクセスできます。
(unsigned int *)
は、&t
をunsigned int
へのポインタに変換します。 *
は、その位置の値を取得します。その最後のステップは正式に未定義の振る舞いをしています。
float
とunsigned int
が異なるサイズの実装(コンパイラ)の場合、動作は何でもかまいません。
これは、floatをint自体に正確に変換するものではありません。指数の
一方、符号なしの値は32ビット(プラットフォームによって決まるエンディアン)です。
ストレートフロート→符号なし整数変換では、浮動小数点の実際の値を、最も近い符号なしの内部に収めるようにしようとします。このコードは、浮動小数点数を意味するものを解釈しようとせずに浮動小数点を構成するビットをそのままコピーします。したがって、1.0fは0x3f800000に変換されます(ビッグエンディアンを前提とします)。
上記のように、プラットフォームに関するかなりの数の仮定があります(プラットフォームによっては、サイズが不一致になり、切り詰めやメモリの破損に至る可能性があります)。とにかく、何が起こっているのかをもっと明白にするために、明示的にmemcpy()を行うことを好みます。
これはです追加の講義として、http://www.wikipedia.org/wiki/Type_punningを参照してください。cocoawithlove.com/2008/04/using-pointers-to-recast-in-c-is-bad.html – Amadeus