
C言語基礎|ビット単位の論理演算
ビットは小さなスイッチ!AND/OR/XOR/NOTで、ON・OFFを思い通りに組み立てよう。
ビット単位の論理演算ってなに?
第3章で学んだ「論理積(AND)」「論理和(OR)」は、条件式の true/false を扱う世界でしたよね。
一方で今回のテーマは、整数の中に詰まっている 0 と 1(ビット)そのものを対象にして、同じような論理演算をします。
イメージとしては、
- 整数 = ビットが並んだスイッチボード
- 0 = OFF、1 = ON
- AND/OR/XOR/NOT で、スイッチをまとめて加工する
という感じです。ハードウェア制御、フラグ管理、ビットマスク、暗号・圧縮、通信プロトコルなど、低レイヤでは頻出の道具になります。

ビット単位の論理演算子(4種類)
ビット単位の論理演算子
| 演算 | 書式 | 意味(ビットごと) | よくある用途 |
|---|---|---|---|
| AND | a & b | 両方1のビットだけ1 | 必要なビットだけ残す(マスク) |
| OR | a | b | どちらか1なら1 | フラグを立てる(セット) |
| XOR | a ^ b | 片方だけ1なら1 | 差分を見る、ビット反転のトリック |
| NOT(補数) | ~a | 0↔1 を全部反転 | 反転、マスクの反転 |
この表の説明
- 4つとも「整数の各ビット」を独立に見て処理します
- 浮動小数点(float や double)には使えません。整数型だけです
- ~ は「補数演算子」と呼ばれることもあります(ビットを全部反転するからです)
0 を偽、1 を真として計算する(ビット版の真理値表)
ビット演算の結果(1ビットだけに注目)
| a | b | a & b | a | b | a ^ b |
|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 0 |
| 0 | 1 | 0 | 1 | 1 |
| 1 | 0 | 0 | 1 | 1 |
| 1 | 1 | 1 | 1 | 0 |
補数(NOT)
| a | ~a |
|---|---|
| 0 | 1 |
| 1 | 0 |
この表の説明
- AND は「両方ONならON」
- OR は「どっちかONならON」
- XOR は「違っていればON」
- NOT は「全部ひっくり返す」
これを、整数の 全ビット に対して同時にやっているのがビット演算です。
図:4ビットでやると一気にイメージできる
4ビット例で図解します(下位4ビットの世界)。

この図の説明
- 左から順に同じ桁(同じビット位置)を見て計算しています
- 実際の unsigned が 16ビットなら16桁、32ビットなら32桁で同じことをやっています
超重要:ビット演算は「フラグ操作」で真価を発揮する
ビット演算が便利な理由は、1つの整数に複数の状態(フラグ)を詰められるからです。
ビットをフラグにする例(8ビット)
| ビット位置 | 意味(例) | マスク値 |
|---|---|---|
| 0 | ログ出力ON | 1 |
| 1 | デバッグON | 2 |
| 2 | 通知ON | 4 |
| 3 | セーフモードON | 8 |
この表の説明
- たとえば、flags の 1ビット目が1なら「デバッグON」みたいに決めます。
- マスク値は 1, 2, 4, 8… と 2の累乗になり、特定ビットだけを狙い撃ちできます。
よく使う操作は次の4つです。
フラグ操作の定番4パターン
| やりたいこと | 例(mask を使う) | 意味 |
|---|---|---|
| ビットを立てる(ON) | flags = flags | mask | ORでそのビットを1にする。 |
| ビットを消す(OFF) | flags = flags & ~mask | 反転マスクでそのビットだけ0にする。 |
| ビットが立ってるか調べる | (flags & mask) != 0 | ANDして残ればON |
| ビットを反転する | flags = flags ^ mask | XORでそのビットだけ反転 |
登場する命令(演算子・関数)の書式と役割
本文に出てきたものを、学習用に整理します。
ビット演算子
| 演算子 | 書式 | 何をする? |
|---|---|---|
| & | a & b | ビットごとのAND |
| | | a | b | ビットごとのOR |
| ^ | a ^ b | ビットごとのXOR |
| ~ | ~a | 全ビット反転(1の補数) |
右シフト
本文のプログラムでは、ビット表示やビット数カウントに右シフトを使っています。
| 演算子 | 書式 | 何をする? | よくある用途 |
|---|---|---|---|
| >> | x >> n | x を右に n ビットずらす | 特定ビットの取り出し |
| >>= | x >>= n | x = x >> n と同じ | ループで順にずらす |
この表の説明
- 右にずらすと、下位ビットを順番に見ていけます
- 例えば (x >> i) & 1U で「i番目のビット」が取り出せます
サンプルプログラム
題材:フラグ管理(ON/OFF/反転/確認)
入力は1つだけ(初期フラグ値)にして、操作結果をビットで表示します。
プロジェクト名:chap7-16-1 ソースファイル名:chap7-16-1.c
// フラグ(ビット)を操作して、結果をビット列で表示する例
#include <stdio.h>
int int_bits(void)
{
// unsigned のビット数を数える(~0U は全ビット1)
unsigned x = ~0U;
int bits = 0;
while (x) {
bits++;
x >>= 1;
}
return bits;
}
void print_bits(unsigned x)
{
for (int i = int_bits() - 1; i >= 0; i--) {
putchar(((x >> i) & 1U) ? '1' : '0');
}
}
int main(void)
{
unsigned flags;
printf("フラグ値(非負整数)を入力してください。\n");
printf("flags = ");
scanf("%u", &flags);
// 例として3つのフラグを使う
const unsigned LOG_ON = 1U; // bit0
const unsigned DEBUG_ON = 2U; // bit1
const unsigned SAFE_ON = 8U; // bit3
putchar('\n');
printf("現在の flags = "); print_bits(flags); putchar('\n');
// 1) デバッグをON(ビットを立てる)
unsigned after_set = flags | DEBUG_ON;
printf("デバッグON後 = "); print_bits(after_set); putchar('\n');
// 2) セーフモードをOFF(ビットを消す)
unsigned after_clear = after_set & ~SAFE_ON;
printf("セーフOFF後 = "); print_bits(after_clear); putchar('\n');
// 3) ログを反転(ビットをひっくり返す)
unsigned after_toggle = after_clear ^ LOG_ON;
printf("ログ反転後 = "); print_bits(after_toggle); putchar('\n');
// 4) デバッグがONか確認(ビットを調べる)
printf("\n判定:デバッグは%sです。\n",
(after_toggle & DEBUG_ON) ? "有効" : "無効");
return 0;
}このプログラムで学べること(説明)
- flags | DEBUG_ON で bit1 を必ず1にする(セット)
- flags & ~SAFE_ON で bit3 を必ず0にする(クリア)
- flags ^ LOG_ON で bit0 を反転する(トグル)
- after_toggle & DEBUG_ON で bit1 が立っているか調べる(テスト)
まとめ:ビット演算は「マスク」で覚えると強い
- & は「残す(マスク)」
- | は「立てる(セット)」
- ~ は「反転マスクを作る」
- ^ は「反転(トグル)」
- は「ビットを取り出すのに便利」
