float b = 1.0f;
int i = b;
int& j = (int&)i;
cout<<j<<endl;
o/p = 1
しかし、次のシナリオでは
float b = 1.0f;
int i = b;
int& j = (int&)b;
cout<<j<<endl;
O/P = 1065353216
両方とも同じ値を持っているため、同じ結果が表示されます...行番号3で変更を行っているときに実際に何が起こっているのか誰か教えてください。
float b = 1.0f;
int i = b;
int& j = (int&)i;
cout<<j<<endl;
o/p = 1
しかし、次のシナリオでは
float b = 1.0f;
int i = b;
int& j = (int&)b;
cout<<j<<endl;
O/P = 1065353216
両方とも同じ値を持っているため、同じ結果が表示されます...行番号3で変更を行っているときに実際に何が起こっているのか誰か教えてください。
最初のものでは、すべてうまくやっています。コンパイラは に変換できfloat b
、int i
精度が失われますが、問題ありません。次に、2 番目の例の実行中にデバッガー ウィンドウを見てください。
ロシア語の IDE インターフェースで申し訳ありません。最初の列は変数名、2 番目は値、3 番目は型です。
ご覧のとおり、float は単純に int として解釈されます。したがって、先頭1
のビットは整数のビットとして解釈され、得られる結果につながります。したがって、基本的には、float のバイナリ表現 (通常は符号ビット、仮数、指数として表されます) を取得し、. として解釈しようとしint
ます。
最初のケースではj
、正しく初期化しており、キャストは不要です。2 番目のケースでは、間違って (つまり、異なる型のオブジェクトに対して) 行っていますが、キャストによってコンパイラがシャットダウンされます。
この 2 番目のケースでは、おそらく1.0
整数として解釈された内部表現が得られます。
Referenceはメモリ割り当てを行わず、ローカル名とそのアドレスのテーブルにエントリを配置するだけです。最初のケースでは、名前「j」は以前にintデータ型に割り当てられたメモリ(変数「i」の場合)を指し、2番目のケースでは名前「j」はfloatデータ型に割り当てられたメモリ(変数「b」の場合)を指します。'j'コンパイラを使用すると、適切なアドレスのデータがintであるかのように解釈されますが、実際にはそこにfloatが配置されているため、1ではなく「奇妙な」数値が得られます。
整数1
と浮動小数点1.0f
は数学的には同じ値かもしれませんが、C++ では型が異なり、表現も異なります。
左辺値を参照にキャストすることはreinterpret_cast
;と同等です。「このメモリの場所にあるものを見て、それらのバイトをint
.
最初のケースでは、メモリには が含まれているため、これらのバイトを期待値int
として解釈します。int
2 番目のケースでは、メモリに が含まれているため、整数として再解釈された浮動小数点数を表すfloat
バイト (または、おそらくそれらの一部のみ、または の場合は余分なバイトも) が表示されます。sizeof(int) != sizeof(float)
お使いのコンピューターでは、おそらく 32 ビットint
と 32 ビットのIEEE float
表現が使用されています。このfloat
値1.0f
には、ゼロの符号ビット、ゼロの指数 (8 ビット値 127、または 2 進数で 01111111 で表される)、および 1 の仮数部 (23 ビット値ゼロで表される) があるため、32 ビットパターンは次のようになります。
00111111 10000000 00000000 00000000
整数として再解釈すると、16 進値0x3f800000
が得られます。これは 10 進数で 1065353216 です。
最初のものは、最初に にキャストb
してから、int
に割り当てi
ます。コンパイラが値を適切に変換するため、これは「適切な」方法です。
2 番目のものはキャストせず、b
のビットを整数として再解釈します。浮動小数点形式を読めば、取得している値を取得している理由が正確にわかります。
内部では、すべての変数は単なるビットの集まりです。これらのビットをどのように解釈するかによって、それらが表す知覚値が変わります。最初のものでは、「認識された」値 (1) を保持するためにビット パターンを再配置しています。2 番目のものでは、ビット パターンを再配置していないため、認識された値が適切に変換されません。