2016-10-23 6 views
-2

私は約1時間このコードを解明しようとしていますが、まだ運がありません。私はどのようにこの作品を理解していないユニオン出力で苦労しています

#include <stdio.h> 
#include <stdlib.h> 

int f(float f) 
{ 
    union un {float f; int i;} u = {f}; 

    return (u.i&0x7F800000) >> 23; 
} 

int main() 
{ 
    printf("%d\n", f(1)); 

return 0; 
} 

は、私は(1)、(2)F、(3)F、(4)Fと異なる結果を得ることはもちろんFを試してみました。私はまた、組合やものについてたくさん読んできました。私が返すから0x7F800000を削除すると、結果は同じになることに気付いたことがあります。私はu.iがどのように生成されているか知りたいですが、明らかにランダムなガベージではありませんが、関数の引数から1つもありません。ここで何が起こっているのですか、それはどのように機能しますか?

答えて

2

これは実際には浮動小数点数がどのようにメモリ内に表現されるかを理解することになります。 (IEEE 754参照)。要するに

、32ビット浮動小数点数は、以下の構造

  • ビット31は、
  • ビット30全体の数に対する符号ビットになりあります - 、23数の指数となり偏っている127
  • ビット22 - 0は、数値の小数部分を表します。これは、10進数(実際には2進数)の前の数字が1になるように正規化されます。組合に関して

、組合が一度にタイプのいずれかを保持することができるコンピュータメモリのブロックであることを思い出し、そう宣言:

union un 
    { 
     float f; 
     int i; 
    }; 

32ビットを作成しています浮動小数点数または整数を保持できるメモリブロック。ここで、浮動小数点パラメータで関数を呼び出すと、その番号のビットパターンがunのメモリ位置に書き込まれます。今度はiメンバを使ってユニオンにアクセスすると、ビットパターンは整数として扱われます。 sは、符号ビット、指数eビットとf小数ビットを表すwhese

したがって、32ビット浮動小数点数の一般的なレイアウトは、seee eeee efff ffff ffff ffff ffff ffffあります。はい、うんざりしています。うまくいけば、例が役に立ちます。

4をIEEE浮動小数点に変換するには、まず7をバイナリに変換します(私は32ビットの数値を4ビットのニブルに分割しました)。

4 = 0000 0000 0000 0000 0000 0000 0000 0111 

さて、、すなわち2のべき乗数としてこれを表現、これを正規化する必要があります。

1.11 x 2^2 

は、ここでは、2の各パワーが(10の累乗を扱うに類似した)場所に右に進小数点を移動することを覚えておく必要があります。全体の符号ビットが0

  • であるように、このから

    は、我々が現在のビットパターン

    1. を生成することができる数の全体の符号が正の指数は2であり、私たちこれは、127の指数が0に格納され、127の指数が255として格納されることを意味します。したがって、指数フィールドは129または1000 0001になります。

    2. 最後に、正規化された数値は1100 0000 0000 0000 0000 000 000です。常に先頭にあると仮定されているため、先行する「1」は削除されています。すべて一緒にこれを置く

    3. は、我々はビットパターンとして持っている:今

      4 = 0100 0000 1110 0000 0000 0000 0000 0000

    、ここで最後の少しビット単位であります0x7F800000で をバイナリで書き出すと、0111 1111 1000 0000 0000 0000 0000 0000となります。これをIEEE浮動小数点数の一般的なレイアウトと比較すると、マスクで選択しているものが指数ビットであることがわかります左に23ビット。

    あなたのプログラムでは、浮動小数点数のバイアスされた指数部が表示されているだけです。一例として、

    #include <stdio.h> 
        #include <stdlib.h> 
    
        int f(float f) 
        { 
         union un {float f; int i;} u = {f}; 
    
         return (u.i&0x7F800000) >> 23; 
        } 
    
        int main() 
        { 
         printf("%d\n", f(7)); 
         return 0; 
        } 
    

    は、我々が期待するように、129の出力を与える。