『C言語雑記』C言語における左シフトと右シフト演算


左に移動
左シフトは、1つの数のすべてのビットを左にいくつかのビットを移動し、Cで<
int i = 1;
i = i << 2;  // i     2 

つまり、1の2進数は000…0001(ここで1の前の0の個数はintの桁数に関係し、32ビットマシン、gccには31個の0がある)で、左に2ビットシフトした後に000…0100となり、つまり10進数の4となるので、左に1ビットシフトするのは2を乗じたものに相当し、では、左シフトnビットは2を乗じたn次方である(符号数が完全に適用されない場合があるが、左シフトが符号変化を引き起こす可能性があるため、以下に理由を説明する)
注意すべき問題の1つは、intタイプの左端のシンボルビットとシフトがシフトされる場合である.intはシンボルのある整形数であり、左端の1ビットはシンボルビット、すなわち0正1負であり、シフト時にオーバーフローが発生することを知っています.例えば、
int i = 0x40000000; //16   40000000, 2   01000000...0000
i = i << 1;

すると、iは1ビット左にシフトすると0 x 8000000、つまり2進数の100000…00000となり、符号ビットが1にセットされ、他のビットはすべて0となり、intタイプで表すことができる最小値となり、32ビットのintという値は-2174748483648となり、オーバーフローする.次にiを1位左に移動するとどうなりますか?C言語では最上位を捨てる処理法を採用し,1を捨てるとiの値は0となる.
左シフトのうち、左シフトのビット数がこの数値タイプの最大ビット数を超えると、コンパイラは左シフトのビット数で型の最大ビット数を除去し、残りの数でシフトします.
int i = 1, j = 0x80000000; // int 32 
i = i << 33;   // 33 % 32 = 1   1 ,i  2
j = j << 33;   // 33 % 32 = 1   1 ,j  0,      

このプログラムをgccでコンパイルすると、コンパイラは左シフトビット数>=タイプ長というwarningを与えます.では実際にi,jが移動するのは1ビット,すなわち33%32後の残数である.
gccではこのルールですが、他のコンパイラが同じかどうかはまだ分かりません.つまり左シフトは、最高位を捨て、0が最低位を補うことです.
右に移動
右シフトの概念は左シフトとは逆に、右にいくつかのビットを移動し、演算子は>>です.右シフトのシンボルビットに対する処理と左シフトは異なり、intタイプなどのシンボル整数の場合、右シフトはシンボルビットを維持します.たとえば、次のようにします.
int i = 0x80000000;
i = i >> 1;  //i      0x40000000,    0xc0000000

すなわち、符号ビットが右に移動する後、正数であれば0、負数であれば1、すなわちアセンブリ言語における算術右に移動する.同様に、移動するビット数がタイプの長さを超えると、剰余金が取られ、剰余金が移動します.負数10100110>>5(文字長が8ビットであると仮定)では11111101が得られる
要するに,Cでは左シフトが論理/算術左シフト(両者は全く同じ)であり,右シフトが算術右シフトであり,シンボルビットは変わらない.実際の応用では,状況に応じて左/右シフトで高速な乗算/除算が可能であり,サイクル効率よりもはるかに高い.
例:
(1)unsigned char x=3; x<<1はいくらですか?x>>1はいくらですか?  (2)char x=3; x<<1はいくらですか?x>>1はいくらですか?(3)char x=-3; x<<1はいくらですか?x>>1はいくらですか?【注】3は2進数で0000011、3は2進数で11111101、プログラム実行時は数値の符号化表示、つまりメモリ内の数値の2進数表示を行います.例えば、プログラムが-3をとるときは11111111101を取りに行きます.
【解析】(1)符号なし数3では、x<<1が左にシフトし、一番左のシフトが落ち、一番右のシフトがゼロになる.00000110になるので、結果は6;x>>1が右にシフトし、符号なしであるため論理的に右にシフトし、一番右にシフトし、一番左にシフトしたビットがゼロになり、000001になるので、結果は1となる.
(2)符号数3がある場合,x<<1が左に1ビットシフトし,最も左のシフトが外れ,最も右のシフトが入ってきたビットがゼロになる.00000110になったので、結果は6でした.x>>1を右にシフトすると、符号数があるため論理右シフトが発生する可能性があり、算術右シフトが発生する可能性があるという点で、C規格では論理右シフトを使用するか算術右シフトを使用するかを明確に指定していない.しかし、多くの機械は算術を使って右に移動し、1億円になったため、結果は1だった.しかし、これは多くの機械がそうであることを言っているだけで、あなたは自分が特別な状況に遭遇しないことを保証することができますか?
(3)符号数−3がある場合,x<<1が左に1ビットシフトし,最も左のシフトが外れ,最も右のシフトが入ったビットがゼロになる.11111010になり、結果は-6になります.1ビット右にシフトすると、シンボル数があるため、論理右シフトが発生したり、算術右シフトが発生したりする可能性があります.ほとんどの機械は算術を用いて右に移動し,11111110になり,結果は−2であった.
まとめ:左シフトでは常にシフトとゼロ補正が行われます.右シフト時の符号なし数はシフトとゼロ補正であり、この場合を論理右シフトと呼ぶ.符号数がある場合は、シフトと一番左のビット(すなわち、最も有効なビットを補う)を補正し、数ビットをシフトすると数ビットを補正し、この場合を算術右シフトと呼ぶことが多い.