はい、わかっています。ダブル値でビット単位の操作を行うのは悪い考えのように思えますが、実際には必要です。
私の質問のために次の段落を読む必要はありません。
Mozilla Tamarin (Actionscript Virtual Machine) の特別な mod を実際に試してみました。その中で、どのオブジェクトにもそのタイプ用に予約された最初の 3 ビットがあります (たとえば double は 7 です)。これらのビットは、プリミティブ データ型 (int のみ 29 ビットなど) の精度を下げます。私の mod では、この領域を 2 ビット拡張する必要があります。つまり、たとえば 2 つの double を追加する場合、これらの最後の 5 ビットを 0 に設定し、計算を行ってから結果をリセットする必要があります。なぜそんなに^^
コードに戻ります。非常によく似た問題を示す最小限の例を次に示します。
double *d = new double;
*d = 15.25;
printf("float: %f\n", *d);
//forced hex output of double
printf("forced bitwise of double: ");
unsigned char * c = (unsigned char *) d;
int i;
for (i = sizeof (double)-1; i >=0 ; i--) {
printf ("%02X ", c[i]);
}
printf ("\n");
//cast to long long-pointer, so that bitops become possible
long long * l = (long long*)d;
//now the bitops:
printf("IntHex: %016X, float: %f\n", *l, *(double*)l); //this output is wrong!
*l = *l | 0x07;
printf("last 3 bits set to 1: %016X, float: %f\n", *l, *d);//this output is wrong!
*l = *l | 0x18;
printf("2 bits more set to 1: %016X, float: %f\n", *l, *d);//this output is wrong!
これを VisualStudio2008 で実行すると、最初の出力は正しくなります。セカンドも。3 番目は、16 進表現と浮動小数点表現の両方で 0 を返しますが、これは明らかに間違っています。4 番目と 5 番目も 16 進数と浮動小数点数の両方でゼロですが、変更されたビットは 16 進数値に表示されます。だから私は、タイプキャストがここで物事を台無しにしたのではないかと思いました。さらに2つの出力:
printf("float2: %f\n", *(double*)(long long*)d); //almost right
printf("float3: %f\n", *d); //almost right
15.25 と表示されていますが、15.2500000000000550670620214078 のはずです。だから私は、ちょっと、それは出力の精度の問題だと思った。もう少し上に変更しましょう:
*l = *l |= 0x10000000000;
printf("float4: %f\n", *d);
繰り返しますが、出力は 15.2519531250000550670620214078 ではなく 15.25(0000) です。奇妙なことに、別の強制的な 16 進出力 (上記のコードを参照) では、d がまったく変更されていません。少しいじってみたところ、ビット 31 (0x80000000) が手動で設定できる最後のビットであることがわかりました。そして聖なるモリ、それは実際に出力に影響を与えます(15.250004)!
そのため、少し迷いましたが、まだ多くの混乱があります。printfは壊れていますか?ここでビッグ/リトルエンディアンの混乱がありますか? ある種のバッファオーバーランを誤って作成していますか?
誰かが興味を持っている場合、元の問題 (タマリンのこと、上記を参照) では、ほとんど逆です。そこでは、最後の 3 ビットが既に設定されています (これは double を表します)。それらをゼロに設定すると正常に機能します(これが元の実装です)。さらに 2 を 0 に設定すると、上記と同じ効果があります (全体の値がゼロになります)。ちなみに、これは出力固有ではありませんが、数学演算もこれらのフロア値で機能するようです(そのように取得された2つの値のmulは0になります)。
どんな助けでも大歓迎です。ご挨拶。