C言語 ビット演算

Last-modified: 2015-07-09 (木) 07:44:59
 
 

ビット演算とは

コンピュータでは、数値はすべて 2 進数として扱われています。
ビット演算では、C 言語で数値をビットごとに操作することができます。

ビット演算の種類

ビット演算には、以下のものがあります。

  • ビット演算子
    • AND (&)
    • OR (|)
    • NOT (~)
    • XOR (^)
  • シフト演算子
    • 左シフト (<<)
    • 右シフト (>>)

XOR 以外は基本的に覚えて、使えるようにして下さい。
論理演算子 (&&||) と混同しないように注意してください

ビット演算子

AND

AND (アンド) 演算子は、どちらも 1 だったら 1 になる演算です。

0101
0111
and)1101
 

上記例は、C言語では以下のようになります。

char a = 0b00000111; // 0x07
char b = 0b00000101; // 0x0d
char c = a & b;      // 0x05

OR

OR (オア) 演算子は、どちらか 1 だったら 1 になる演算です。

1101
0101
or)1100
 

上記例は、C言語では以下のようになります。

char a = 0b00000101; // 0x05
char b = 0b00001100; // 0x0c
char c = a | b;      // 0x0d

NOT

NOT (ノット) 演算子は、すべてのビットを反転 させる演算です。

1010
not)0101
 

上記例は、C言語では以下のようになります。

char a = 0b00000101; // 0x05
char b = ~a;         // 0x0a

XOR

XOR (エックスオア) 演算子は、どちらか片方だけが 1 だったら 1 になる演算です。
Ex-OR, Exclusive-OR (エクスクリシーブ オア) とも呼ばれます。

1001
0101
xor)1100

上記例は、C言語では以下のようになります。

char a = 0b00000101; // 0x05
char b = 0b00001100; // 0x0c
char c = a ^ b;      // 0x09

シフト演算子

左シフト

データを左 (上位ビット側) にずらします。
はみ出た左の桁は捨てられ、余った右の桁には、ゼロが入ります。

たとえば、次のような 1 バイトのデータを左にシフトした場合は、以下の通りになります。

種別2進数10進数
元データ10010101149
左 1シフト0010101048
左 2シフト0101010096
 

C言語では、以下のように書きます。

char a = 0x01;

a = a << 1; // 1ビット左にシフト
a <<= 1;    // ↑の短縮表記

a <<= n; // n ビット左にシフト

右シフト

テンプレ使用法

n ビット目が 1 かどうか調べる

レジスタ XXX の n ビット目 (最下位ビットが 0 ビット目) が 1 かどうか調べるには、以下のようにします。

if(XXX & (1 << n)){
    // ビットが立っていた時の処理
}

n ビット目が 0 かどうか調べる

レジスタ XXX の n ビット目 (最下位ビットが 0 ビット目) が 0 かどうか調べるには、以下のようにします。

if(!(XXX & (1 << n))){
    // ビットが立っていない時の処理
}

n ビット目を 1 にする

レジスタ XXX の n ビット目 (最下位ビットが 0 ビット目) のみを 1 にするには、以下のようにします。

XXX |= 1 << n;

n ビット目を 0 にする

レジスタ XXX の n ビット目 (最下位ビットが 0 ビット目) のみを 0 にするには、以下のようにします。

XXX &= ~(1 << n);

n ビット目を反転する

レジスタ XXX の n ビット目 (最下位ビットが 0 ビット目) を反転するには、以下のようにします。

XXX ^= 1 << n;

これによって、ビットが 1 だった場合 0 になり、0 だった場合 1 になります。

n ビット目を x にする

レジスタ XXX の n ビット目 (最下位ビットが 0 ビット目) を x (変数の値) にするには、以下のようにします。

int x = 0;

XXX = (XXX & ~(1 << n)) | x << n;

8 bit ローテート

以下の様に、巡回ビットシフトすることを、ローテートといいます

種別2進数10進数
元データ000000011
1 回目000000102
2 回目000001004
3 回目000010008
4 回目0001000016
5 回目0010000032
6 回目0100000064
7 回目10000000128
8 回目000000011
9 回目000000102
 

上記操作をC言語で記述すると、以下のようになります。

char a = 0x01;

a = (a << 1) | ((a >> 7) & 0x01); // この行を繰り返す
 

超越者向けビット演算

可読性は非常に悪いです。

1になっている一番下の桁を取得する

レジスタ XXX の 1になっている一番下の桁をxに格納するには、以下のようにします。

int x;

x = XXX & (-XXX);

1になっている一番下の桁を0にする

レジスタ XXX の 1になっている一番下の桁を0にするには、以下のようにします。


XXX &= XXX - 1;

ifを使わない条件付きビットセット&ビットクリア

if(f) XXX |= mask; else XXX &= ~mask; と同等の動作をさせるには、以下のようにします。


unsigned int f;    // 0か1の値を取る 1でセット 0でクリア
unsigned int mask; // ビットマスク

XXX ^= (-f ^ XXX) & mask;

参考資料