目次 |
ビット演算とは
コンピュータでは、数値はすべて 2 進数として扱われています。
ビット演算では、C 言語で数値をビットごとに操作することができます。
ビット演算の種類
ビット演算には、以下のものがあります。
- ビット演算子
- AND (&)
- OR (|)
- NOT (~)
- XOR (^)
- シフト演算子
- 左シフト (<<)
- 右シフト (>>)
XOR 以外は基本的に覚えて、使えるようにして下さい。
論理演算子 (&& や ||) と混同しないように注意してください。
ビット演算子
AND
AND (アンド) 演算子は、どちらも 1 だったら 1 になる演算です。
0 | 1 | 0 | 1 | |
0 | 1 | 1 | 1 | |
and) | 1 | 1 | 0 | 1 |
上記例は、C言語では以下のようになります。
char a = 0b00000111; // 0x07
char b = 0b00000101; // 0x0d
char c = a & b; // 0x05
OR
OR (オア) 演算子は、どちらか 1 だったら 1 になる演算です。
1 | 1 | 0 | 1 | |
0 | 1 | 0 | 1 | |
or) | 1 | 1 | 0 | 0 |
上記例は、C言語では以下のようになります。
char a = 0b00000101; // 0x05
char b = 0b00001100; // 0x0c
char c = a | b; // 0x0d
NOT
NOT (ノット) 演算子は、すべてのビットを反転 させる演算です。
1 | 0 | 1 | 0 | |
not) | 0 | 1 | 0 | 1 |
上記例は、C言語では以下のようになります。
char a = 0b00000101; // 0x05
char b = ~a; // 0x0a
XOR
XOR (エックスオア) 演算子は、どちらか片方だけが 1 だったら 1 になる演算です。
Ex-OR, Exclusive-OR (エクスクリシーブ オア) とも呼ばれます。
1 | 0 | 0 | 1 | |
0 | 1 | 0 | 1 | |
xor) | 1 | 1 | 0 | 0 |
上記例は、C言語では以下のようになります。
char a = 0b00000101; // 0x05
char b = 0b00001100; // 0x0c
char c = a ^ b; // 0x09
シフト演算子
左シフト
データを左 (上位ビット側) にずらします。
はみ出た左の桁は捨てられ、余った右の桁には、ゼロが入ります。
たとえば、次のような 1 バイトのデータを左にシフトした場合は、以下の通りになります。
種別 | 2進数 | 10進数 | |||||||
元データ | 1 | 0 | 0 | 1 | 0 | 1 | 0 | 1 | 149 |
---|---|---|---|---|---|---|---|---|---|
左 1シフト | 0 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 48 |
左 2シフト | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 0 | 96 |
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進数 | |||||||
元データ | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |
---|---|---|---|---|---|---|---|---|---|
1 回目 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 2 |
2 回目 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 4 |
3 回目 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 8 |
4 回目 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 16 |
5 回目 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 32 |
6 回目 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 64 |
7 回目 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 128 |
8 回目 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |
9 回目 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 2 |
上記操作を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;