ビット演算子


ビット単位の演算を行うものをビット演算(bitwise operator)といいます。ビット論理演算子(bitwise logical operator)ともいいます。

まずはサンプルを見てみましょう。

ソースコード

源文件
  1|/* bit01.c */
  2|
  3|#include <stdio.h>
  4|
  5|int main(void)
  6|{
  7|  unsigned short a, b;
  8|
  9|  a = 1;
 10|  b = 3;
 11|
 12|  printf("a & b = %d\n", a & b);
 13|  printf("a | b = %d\n", a | b);
 14|  printf("a ^ b = %d\n", a ^ b);
 15|
 16|  return 0;                                                                 
 17|}

実行結果

a & b = 1
a | b = 3
a ^ b = 2


ここでは、short 型を2バイトとします。このとき、

1を2進法で表すと、0000 0000 0000 0001

3を2進法で表すと、0000 0000 0000 0011



ビット演算の利用方法

「ビット演算なんてどんなとき使うの?」

ソースコード

源文件

  1|/* bit02.c */                                                               
  2|
  3|#include <stdio.h>
  4|
  5|#define CAT 1 
  6|#define DOG 2
  7|#define RAT 4
  8|#define RABBIT 8
  9|
 10|int main(void)
 11|{
 12|  int a = CAT | DOG;                /* Aさんのペット */
 13|  int b = RAT;                      /* Bさんのペット */
 14|  int c = CAT | DOG | RAT | RABBIT; /* Cさんのペット */
 15|  int d = DOG | RAT;                /* Dさんのペット */
 16|
 17|  printf("Aさんのペット(猫=%d, 犬=%d, ネズミ=%d, ウサギ=%d)\n",
 18|         (a & CAT) != 0, (a & DOG) != 0, (a & RAT) != 0, (a & RABBIT) != 0)    ;
 19|  printf("Bさんのペット(猫=%d, 犬=%d, ネズミ=%d, ウサギ=%d)\n",
 20|         (b & CAT) != 0, (b & DOG) != 0, (b & RAT) != 0, (b & RABBIT) != 0)    ;
 21|  printf("Cさんのペット(猫=%d, 犬=%d, ネズミ=%d, ウサギ=%d)\n",
 22|         (c & CAT) != 0, (c & DOG) != 0, (c & RAT) != 0, (c & RABBIT) != 0)    ;
 23|  printf("Dさんのペット(猫=%d, 犬=%d, ネズミ=%d, ウサギ=%d)\n",
 24|         (d & CAT) != 0, (d & DOG) != 0, (d & RAT) != 0, (d & RABBIT) != 0)    ;
 25|
 26|  return 0;
 27|}

実行結果

Aさんのペット(猫=1, 犬=1, ネズミ=0, ウサギ=0)
Bさんのペット(猫=0, 犬=0, ネズミ=1, ウサギ=0)
Cさんのペット(猫=1, 犬=1, ネズミ=1, ウサギ=1)
Dさんのペット(猫=0, 犬=1, ネズミ=1, ウサギ=0)


飼っているペットを「|」演算子でつないています。ここで、Aさんがネズミを飼っているかどうかを調べるときは(a & RAT)の値を調べます。飼っていなければ0、飼っていれば0以外の値をなります。そのたの動物についても同じように調べることができます。

どうしてこんなことができるのでしょうか。それには、各ペットに割当られている数字にヒントがあります。例えばプログラム冒頭部分の「#define CAT 1」で、CATに1割当てています。これらの数字をよく見ると、CAT,DOG,RAT,RABBITの値が2倍、2倍となっていることに気づきます。これを2進法で表してみましょう。

CAT
0000 0001
DOG
0000 0010
RAT
0000 0100
RABBIT
0000 1000

各ペットのビットで1となっているのは一つのみです。さて、それぞれのペットのビットが1になっているかどうかは「ペットの値 & 調べたい値」でわかります。つまり、調べたい値のそのペットのビットが1になっていれば、0以外の値になります。例えば(CAT | DOG)の値は(0000 0011)です。これに CAT(0000 0001)が含まれているかどうかをしらべるには

(0000 0001) & (0000 0011)

の値を調べます。この演算結果は0以外の値となります。


補数の演算子

この他に「~」という演算子(補数演算子)があります。このは、各ビットの反転させます。

ソースコード

源文件
  1|/* bit03.c */
  2|
  3|#include <stdio.h>
  4|
  5|int main(void)
  6|{
  7|  int a = 10;
  8|
  9|  printf(" a = %08X\n~a = %08X\n", a, ~a);                                  
 10|
 11|  return 0;
 12|}

実行結果

 a = 0000000A
~a = FFFFFFF5


10は32ビットで表すと

(0000 0000 0000 0000 0000 0000 0000 1010)

となり、これを16進数に直すと0x0000000A。ビット反転すると

(1111 1111 1111 1111 1111 1111 1111 0101)

となり、これを16進数に直すと0xFFFFFFF5です。

シフト演算子

シフト演算子というものもあります。これは、ビットを右また左にずらす演算子です。かけ算、割り算を高速で処理することができます。

「>>」は、ビットを右にずらします。(1000 0000)のビットを一つ右にずらすと(0100 0000)となります。左にできた隙間は0で埋め、右にはみ出たビットを無視します。これは、値が2分の1になりました。さらにビットを一つ右にシフトすると(0010 0000)となり、またまた値が2分の1になりました。

「>>」を右シフト演算子(right-shift operator)といいます。逆に「<<」を左シフト演算子(left-shift operator)といいます。

ソースコード

源文件
  1|/* shift01.c */                                                             
  2|
  3|#include <stdio.h>
  4|
  5|int main(void)
  6|{
  7|  short a = 12, b = 100, c = -50;
  8|
  9|  printf("%dを左に1ビットシフト---%d\n", a, a << 1);
 10|  printf("さらに1ビット左シフト---%d\n", a << 2);
 11|  printf("さらに1ビット左シフト---%d\n", a << 3);
 12|  printf("さらに1ビット左シフト---%d\n", a << 4);
 13|  printf("\n");
 14|  printf("%dを右に1ビットシフト---%d\n", b, b >> 1);
 15|  printf("さらに1ビット右シフト---%d\n", b >> 2);
 16|  printf("さらに1ビット右シフト---%d\n", b >> 3);
 17|  printf("さらに1ビット右シフト---%d\n", b >> 4);
 18|  printf("\n");
 19|  printf("%dを右に1ビットシフト---%d\n", c, c >> 1);
 20|  printf("%dを左に1ビットシフト---%d\n", c, c << 1);
 21|
 22|  return 0;
23|}

実行結果

12を左に1ビットシフト---24
さらに1ビット左シフト---48
さらに1ビット左シフト---96
さらに1ビット左シフト---192

100を右に1ビットシフト---50
さらに1ビット右シフト---25
さらに1ビット右シフト---12
さらに1ビット右シフト---6

-50を右に1ビットシフト----25
-50を左に1ビットシフト----100
Chapter3 @ C言語目録 @ HomeWork List @ 昭亮's Homepage