別々に送信される 3 つの符号なしバイトがあります。
[byte1, byte2, byte3]
これらを符号付き 32 ビット値に変換する必要がありますが、負の値の符号を処理する方法がよくわかりません。
int32 の上位 3 バイトにバイトをコピーしてから、すべてを右にシフトすることを考えましたが、予期しない動作が発生する可能性があることを読みました。
これを処理する簡単な方法はありますか?
表現は 2 の補数を使用しています。
別々に送信される 3 つの符号なしバイトがあります。
[byte1, byte2, byte3]
これらを符号付き 32 ビット値に変換する必要がありますが、負の値の符号を処理する方法がよくわかりません。
int32 の上位 3 バイトにバイトをコピーしてから、すべてを右にシフトすることを考えましたが、予期しない動作が発生する可能性があることを読みました。
これを処理する簡単な方法はありますか?
表現は 2 の補数を使用しています。
これはかなり古い質問ですが、最近 (24 ビットのオーディオ サンプルを処理しながら) 同じことをしなければならず、独自の解決策を書きました。この回答と同様の原則を使用していますが、より一般的であり、コンパイル後により良いコードを生成する可能性があります。
template <size_t Bits, typename T>
inline constexpr T sign_extend(const T& v) noexcept {
static_assert(std::is_integral<T>::value, "T is not integral");
static_assert((sizeof(T) * 8u) >= Bits, "T is smaller than the specified width");
if constexpr ((sizeof(T) * 8u) == Bits) return v;
else {
using S = struct { signed Val : Bits; };
return reinterpret_cast<const S*>(&v)->Val;
}
}
これにはハードコーディングされた数学はありません。単にコンパイラに作業を任せて、数値を符号拡張する最良の方法を見つけます。特定の幅では、 x86のMOVSXなど、アセンブリにネイティブの符号拡張命令を生成することさえできます。
この関数は、N ビットの数値を、拡張したい型の下位 N ビットにコピーしたことを前提としています。たとえば、次のようになります。
int16_t a = -42;
int32_t b{};
memcpy(&b, &a, sizeof(a));
b = sign_extend<16>(b);
もちろん、任意の数のビットに対して機能し、データを含む型の全幅に拡張します。