これはクエイクIIIアリーナから高速逆平方根の実装です:このポインタキャストは厳密なエイリアシング規則を破棄しますか?
float Q_rsqrt(float number)
{
long i;
float x2, y;
const float threehalfs = 1.5F;
x2 = number * 0.5F;
y = number;
i = * (long *) &y; // evil floating point bit level hacking
i = 0x5f3759df - (i >> 1); // what?
y = * (float *) &i;
y = y * (threehalfs - (x2 * y * y)); // 1st iteration
// y = y * (threehalfs - (x2 * y * y)); // 2nd iteration, this can be removed
return y;
}
私はlong int型i
がフロートy
の(long *
にキャスト)アドレスに間接参照値をとることに気づきました。次にコードはi
の参照を、のy
にあるアドレス(キャストはfloat *
)に格納します。
i
はy
と同じタイプではないため、厳密なエイリアシングルールが破られますか?
値が逆参照されていて、がコピーされていると思われます。;操作はオリジナルではなくコピーで実行されます。
私はそれが少なくともsizeof(long)!= sizeof(float)と同じくらい長いと思います。 –
'sizeof'はエイリアシング違反かどうかは関係ありません。 –
書かれているコードは 'float'のように' long'が32ビットの値であると仮定しています。コンパイラが何が起こっているのかを「見る」ことができるので、私は禁止されていますが、ポインタのキャストは面倒なようですが[ポインタがどこかに格納され、後で驚くような方法で使用されるシナリオとは異なります。私はエイリアシングの問題は、とにかくうまくいくケースでは、コード生成なしで、 '(unsigned char *)'への中間のキャストで処理できると思います。私自身の傾向として、代わりに 'union'を使うことがあります。まだ移植可能ではありませんが、コンパイラーは、組合がエイリアスになることを期待するべきです。 – supercat