2016-10-24 5 views
1

以下のコードに示すように、longnumのビットをd1d2の2つのdoubleにコピーしようとしています。ポインタキャスト+逆参照それぞれ「ビットごとに」および「ビットごとに」となります。longと異なる値をコピーした2つのdoubleが

# include <stdio.h> 

int main(void) { 
    long longnum = 0xDDDDDDDDDDDDDDDD; 
    double d1 = *((double*)(&longnum)); 
    double d2 = longnum & 0xFFFFFFFFFFFFFFFF; 

    printf("%ld\n\n",longnum); 
    printf("%lf\n\n",d1); 
    printf("%lf\n",d2); 
    return 0; 
} 

下の出力に示すように、両方のダブルスが同じ方法で印刷されないという問題があります。

-2459565876494606883 

-1456815990147462891125136942359339382185244158826619267593931664968442323048246672764155341958241671875972237215762610409185128240974392406835200.000000 

15987178197214945280.000000 

​​の大きさ、重の最大サイズを考えると、実際に印刷された2倍の賢明な出力だ巨大な数だと私には思えます。

+3

とにかく厳密なエイリアシングルールのためです。 –

+2

「long」は必ず「double」と同じサイズである必要はありません。 –

+0

1)正しいサイズの**符号なし**固定幅タイプを使用する必要があります。 **そして** '_Static_assert'を使って' double'が同じサイズを持つようにします。それでも実装定義はされますが、少なくとも定義されていない動作は呼び出されません。 – Olaf

答えて

3

&マスクは何もしません。すべての1とANDされた数は同じ数です。上記の行は、

double d2 = longnum; 

とは異なります。この行はビットの再解釈を行いません。代わりにd2を、longnumの値を最もよく表すdoubleに設定します。値は似ています。ビットパターンはまったく異なります。

あなたがしようとしていることを行う最善の方法は、ユニオンを使用することです。組合はtype punningを実行する最良の方法です。あなたはd1で行った

union { 
    long l; 
    double d; 
} u; 

u.l = longnum; 
printf("%f\n\n", u.d); 

使用ポインタとして技術的に未定義の動作を呼び出します。これは一般的なイディオムであり、実際にはうまくいくでしょうが、ポインタで型打ちを避けるべきです。

+0

"ユニオンは最も直接的な方法です" - 実際には、1つのタイプが 'char'でない場合、それらは唯一の準拠の方法です。 – Olaf

+1

しかし、このタイプのパンニングは違法です。それを使用することを提案しないでください。 –

+0

@EugeneSh .:ハァッか。標準では、 'union'のための1つのアプリケーションとして明示的に許可しています。もちろん、すべての実装が定義されています。 – Olaf

0

あなたの問題は、あなたが間違ってメモリの内容を取り、それが倍精度フォーマットであると仮定されている上に行って、

d1 = *((double*)(&longnum)); 

です。あなたは以下のことでそれを行う場合

は:

d1 = (double) longnum; 

その後、8バイトの整数であるメモリ空間longnumの内容は、は適切を変換し、その後でメモリに適切にを保存れますd1が指す位置。 そして、d1の内容が正しいでしょう。 は、「倍精度浮動小数点形式」についてのウィキペディアページを読むことをお勧めします。

浮動小数点値(または倍精度値)の値は、整数とは異なる方法でメモリに格納されます。 https://en.wikipedia.org/wiki/Double-precision_floating-point_format

+2

これはビットをコピーしないので、値をコピーします。私はビットをコピーすることを意図していると信じています。 –

+0

ビットパターンの再解釈だけでなく、 'long'-' double' _conversion_を実行します。全く違うもの。 – Olaf

関連する問題