第17回

ビットシフト

00/06/29 サンプルプログラムのインデントを改善した
98/11/06 IE4.xに対応させた
98/04/29メールアドレス訂正

貴方のコンピュータが、1バイトが8ビットで、int型変数のサイズが2バイト(16ビット)だとします。
int型の16(10進数)を2進数にすると、
10進数  2進数                 16進数
 1    : 0000 0000 0000 0001 : 0x1
 2    : 0000 0000 0000 0010 : 0x2
 3    : 0000 0000 0000 0011 : 0x3
 4    : 0000 0000 0000 0100 : 0x4
 5    : 0000 0000 0000 0101 : 0x5
         ( 中 略 )
13    : 0000 0000 0000 1101 : 0xd
14    : 0000 0000 0000 1110 : 0xe
15    : 0000 0000 0000 1111 : 0xf
16    : 0000 0000 0001 0000 : 0x10
ですから、0000000000010000となります。

C言語では、こういったビット列を、指定したビット数だけ左右にズラすことができます。そのことをビットシフトといいます。ビットシフトする場合、左シフト演算子<<と、右シフト演算子>>の2つを以下のように使います。

ビット列<<左へビットシフトする桁数
ビット例>>右へビットシフトする桁数

つまり、16>>4116<<4256ということになります。

10進数       2進数                  16進数
16>>4    1 : 0000 0000 0000 0001  : 0x1
        16 : 0000 0000 0001 0000  : 0x10
16<<4  256 : 0000 0001 0000 0000  : 0x100

以下は、int型変数の値(16進数でabc)を、左右へ4、8ビット分シフトさせた値を出力するプログラムです。
#include<stdio.h>
main(){
    int a=0xabc;

    printf("0xabc>>4 : 0x%x\n",a>>4);
    printf("0xabc>>8 : 0x%x\n",a>>8);
    printf("0xabc<<4 : 0x%x\n",a<<4);
    printf("0xabc<<8 : 0x%x\n",a<<8);
}

実行結果

0xabc>>4 : 0xab
0xabc>>8 : 0xa
0xabc<<4 : 0xabc0
0xabc<<8 : 0xbc00
それではこれはどうでしょう。
以下は、int型変数の値(16進数でabcd)を、右へ4、8、12、16ビット分シフトさせた値を出力するプログラムです。実行結果を予想してみて下さい。
#include<stdio.h>
main(){
    int a=0xabcd;
    printf("0xabcd>>4 : 0x%x\n",a>>4);
    printf("0xabcd>>8 : 0x%x\n",a>>8);
    printf("0xabcd>>12: 0x%x\n",a>>12);
    printf("0xabcd>>16: 0x%x\n",a>>16);
}
で、実行結果は、貴方の予想に反して(?)以下のようになります。
0xabcd>>4 : 0xfabc
0xabcd>>8 : 0xffab
0xabcd>>12: 0xfffa
0xabcd>>16: 0xffff
見ての通り、右シフトによって空いた部分に、0ではなくfが入っています。 その理由を説明したいと思います。
(int)0xabcdは、10進数にすると-21555、そう、負の整数です。
負の整数(int型の場合、-32768から-1、つまり0x8000から0xffff)の場合、右シフトによって空いた部分は、0ではなくて符号ビットが入ります。上記プログラムでは、4ビットづつ右シフトしています。つまり右シフトする度に空く4ビット全てに1が入ります。つまり16進数で0xfが入る訳です。

例えば、(int)0x7fffは、正の整数(32767)ですので、4ビットづつ右シフトすると・・・
              16進数   10進数 
0x7fff >>  4 : 0x07ff : 2047
0x7fff >>  8 : 0x007f : 127
0x7fff >> 12 : 0x0007 : 7
0x7fff >> 16 : 0x0000 : 0
 
といった結果になります。それに対して、負の整数である(int)0x8000(10進数で-32768)の場合は、以下のようになります。
              16進数   10進数
0x8000 >>  4 : 0xf800 : -2048
0x8000 >>  8 : 0xff80 : -128
0x8000 >> 12 : 0xfff8 : -8
0x8000 >> 16 : 0xffff : -1
つづく。

[メニュー][第16回][第18回]

いーざ
email:CQP00202@nifty.ne.jp