厄介なハックを試みることもできますが、エンディアン性に問題があります。変換するために何をするにしても、コンパイラfloorは、結果の最も重要な部分と重要でない部分になりたいことをどのように認識しているfractionのでしょうか? メモリの再解釈に依存するソリューションは、あるエンディアンでは機能しますが、別のエンディアンでは機能しません。
次のいずれかを行う必要があります。
(1) 変換を明示的に定義します。short16 ビットと仮定すると、次のようになります。
unsigned int val = (x.floor << 16) + x.fraction;
(2) 2 つの short ではなくメンバーをFixed持つように変更し、必要に応じて構成するのではなく、必要に応じて分解します。int
足し算を高速にしたい場合は、(2) を実行する必要があります。64 ビット型の場合は、分解せずに乗算を行うこともできますunsigned int result = (((uint64_t)x) * y) >> 16。
ちなみに、厄介なハックは次のとおりです。
unsigned int val;
assert(sizeof(Fixed) == sizeof(unsigned int)) // could be a static test
assert(2 * sizeof(unsigned short) == sizeof(unsigned int)) // could be a static test
memcpy(&val, &x, sizeof(unsigned int));
これは、Fixed にパディングがない (そして整数型にはパディング ビットがない) ビッグ エンディアン システムで機能します。リトルエンディアン システムでは、Fixed のメンバーを別の順序にする必要があります。これが厄介な理由です。memcpy を介したキャストが正しい場合もあります (この場合、これは「厄介なハック」ではなく「トリック」です)。これはちょうどそれらの時間の 1 つではありません。