次のコードはどのように機能し、変数は何を意味しますか:
y = (x << shift) | (x >> (sizeof(x)*CHAR_BIT - shift));
循環シフトの記事で見つけましたが、これがどのように機能するかについての説明はありません。
次のコードはどのように機能し、変数は何を意味しますか:
y = (x << shift) | (x >> (sizeof(x)*CHAR_BIT - shift));
循環シフトの記事で見つけましたが、これがどのように機能するかについての説明はありません。
これは循環シフトを行う方法です。それx
が8ビットだとします。
+----+----+----+----+----+----+----+----+ | | x1 x2 x3 x4 x5 x6 x7 x8 | x1 x2 x3 x4 x5 x6 x7 x8 | +----+----+----+----+----+----+----+----+
次に、それを 3 だけ左にシフトすると、次のようになります。
+----+----+----+----+----+----+----+----+ | | x4 x5 x6 x7 x8 0 0 0 | +----+----+----+----+----+----+----+----+
現在、CHAR_BIT*sizeof(x)
は のビット幅と同じ8 です。したがって、右にx
シフトすると次のようになります。x
8 - 3
+----+----+----+----+----+----+----+----+ | | 0 0 0 0 0 x1 x2 x3 | +----+----+----+----+----+----+----+----+
ORを取ると、次のようになります。
+----+----+----+----+----+----+----+----+ | | x4 x5 x6 x7 x8 x1 x2 x3 | x4 x5 x6 x7 x8 x1 x2 x3 | +----+----+----+----+----+----+----+----+
これは、型の幅に等しい量だけシフトすることは移植性がないため、技術的に移植性がありません。したがって、シフトが 8 の場合、左シフトは間違っており、シフトが 0 の場合、右シフトは間違っています。間違っている。ただし、これは実際には、タイプの幅だけシフトする場合の 3 つの一般的な動作すべてで機能します。(実際には、シフト量は、型のビット幅またはより大きな数のいずれかのモジュロで減少します。)
これは循環シフトまたは「ローテーション」と呼ばれます。これは、左にシフトアウトされたビットが右にシフトインされるためです。
洗練されたコンパイラは、実際にコードをハードウェア回転命令にまでコンパイルします。
CHAR_BIT
はバイトあたりのビット数で、常に 8 である必要があります。
shift
循環的に左にシフトするビット数です。したがって、左にシフトアウトされたビットは右に戻ります。
1110 0000 << 2 results in:
1000 0011
例のコード:
y = (x << 2) | (x >> (8 - 2));
(x << shift)
'シフト'ビット数を左にシフトし、シフトアウトされたビットを返します
(x >> (sizeof(x)*CHAR_BIT - shift));
それらのビットを収容するためのスペースを作ります
CHAR_BIT
はcharのビット数であるため、ほとんどの場合8です。Cでは、一度に1ビットを処理するのではなく、少なくともcharビット数を処理します。これが、得られる粒度です。
一般に、
charの場合、ビットローテーションを実行するときは、8ビットフィールド(1バイト)で実行します。
intの場合、回転を実行するときは、32ビットフィールド(4バイト)で実行します。
8ビットの例:
x = 11010101
shift = 2
x << (shift) = 01010100 //shifted left by 2 bits
= x >> ((1 * CHAR_BIT) - shift)
= x >> (6)
= 00000011 //shifted right by 6bits
OR
これらをビット単位で与える
01010100 //x << 2
00000011 //x >> 6
________
01010111
これは、2ビットの循環シフト値です。
これは、符号なしタイプでのみ機能します。符号付きの負の数の場合、左端のビットは、右シフト演算子(> >>")によって最上位ビット(1-s)の値に置き換えられます。
私はそれを次のように書きます:
y = (x << shift) | ( (x >> (sizeof(x)*CHAR_BIT - shift)) & (0x7F >> (sizeof(x)*CHAR_BIT - shift) );
ここで「|」の前に 演算子では、最初のnビット(n = sizeof(x)* CHAR_BIT-シフト)がゼロになっていることを確認します。また、xは短い(2バイト長)と仮定します。したがって、タイプにも依存します。