質問

私は宿題で誰かを助けていて、この奇妙な問題に遭遇しました。問題は、署名された整数のバイトの順序を逆にする関数を記述することです(これがとにかく関数の指定方法です)、これは私が思いついたソリューションです。

int reverse(int x)
{
    int reversed = 0;

    reversed = (x & (0xFF << 24)) >> 24;
    reversed |= (x & (0xFF << 16)) >> 8;
    reversed |= (x & (0xFF << 8)) << 8;
    reversed |= (x & 0xFF) << 24;

    return reversed;
}

合格した場合 0xFF000000 この機能に、最初の割り当ては 0xFFFFFFFF. 。何が起こっているのか本当にわかりませんが、署名されたものと署名されていないもの、またはそのようなものの間のコンバージョンとの関係があることを知っています。

どちらかを追加した場合 ul0xFF それは正常に動作します。これは、署名されてから署名されたものに変換されるか、その方向に変換されることを余儀なくされているためです。結果のコードも変更されます。なしで ul SPECISIERはSAR(Shift Arithmetic Right)を使用しますが、署名されていないように、意図したようにSHRを使用します。

誰かが私のためにこれに光を当てることができれば本当に感謝しています。私はこのことを知っているはずです、そして私は私がやったと思ったが、私はここで何が起こっているのか本当に分からない。

前もって感謝します!

役に立ちましたか?

解決

以来 x aです 署名 量、結果 (x & (0xFF << 24)) また、署名されている0xff000000です ネガティブ 上部(サイン)ビットが設定されているための番号。 >> オペレーター int (署名された値)が実行されます サインエクステンション (編集:この動作は未定義であり、実装固有ですが)値が右にシフトされると、1の符号ビット値が伝播されます。

次のように関数を書き換えて、署名されていない値だけで作業する必要があります。

unsigned reverse(unsigned x)
{
    unsigned int reversed = 0;

    reversed = (x & (0xFF << 24)) >> 24;
    reversed |= (x & (0xFF << 16)) >> 8;
    reversed |= (x & (0xFF << 8)) << 8;
    reversed |= (x & 0xFF) << 24;

    return reversed;
}

他のヒント

あなたの結果から、私たちはあなたが32ビットマシンにいることを推測することができます。

(x & (0xFF << 24)) >> 24

この表現で 0xFF です int, 、 それで 0xFF << 24 またです int, 、 そのまま x.

ビットワイズを実行するとき & 2つの間 int, 、結果もandです int この場合、値はです 0xFF000000 32ビットマシンでは、サインビットが設定されていることを意味するため、負の数があります。

負の値を持つ署名型タイプのオブジェクトで右シフトを実行した結果は、実装定義です。あなたの場合、標識提示の算術シフトが右に実行されます。

署名されていないタイプを正しくシフトすると、バイト反転関数を期待していた結果が得られます。ビットワイズのオペランドを作成することでこれを達成できます & オペランド両方のオペランドの符号なしタイプへの変換を強制する署名のないタイプ。 (これは、署名された任意の実装に当てはまります int のすべての可能な範囲の正の値を保持することはできません unsigned int これはほぼすべての実装です。)

署名型タイプの正しいシフトは実装定義です。特に、コンパイラは喜んで算術的または論理的なシフトを自由に行うことができます。これは、あなたが扱っている具体的な価値が肯定的であるかどうかに気付かないものですが、それがネガティブになるとすぐにあなたはtrapに陥るかもしれません。

それをしないでください、これはポータブルではありません。

x 署名されているので、最高のビットがサインに使用されます。 0xff000000は「ネガティブ0x7f000000」を意味します。シフトを行うと、結果は「サイン拡張」です。左側に追加されたバイナリ桁は、右にシフトされた前者のMSBを置き換えることですが、常に値の記号と同じです。それで

0xFF000000 >> 1 == 0xFF800000
0xFF000000 >> 2 == 0xFFC00000
0xFF000000 >> 3 == 0xFFE00000
0xFF000000 >> 4 == 0xFFF00000

シフトされている値が署名されていない場合、またはシフトが左に向かっている場合、新しいビットは0になります。これは、標識拡張が機能する署名値の右シフトのみです。

署名された整数と符号なしの両方の整数を備えたALプラットフォームで同じ動作をしたい場合は、変更します

(x & (0xFF << 24)) >> 24

の中へ

(x >> 24) & 0xFF

これがJavaコードの場合、 '>>>'を使用する必要があります。これは署名されていない正しいシフトです。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top