🇯🇵 日本語 | 🇺🇸 English

第42回 ビット演算

2進数レベルでデータを操作するビット演算子を学びましょう。

📖 このページで覚えること
✅ 最低限ここだけ覚える
  • &(AND), |(OR), ^(XOR), ~(NOT)
  • <<(左シフト)=×2, >>(右シフト)=÷2
⭐ 余裕があれば読む
  • フラグのON/OFF管理
  • ビットマスクで特定ビット抽出
  • 符号付き右シフトは処理系依存

ビット演算とは

コンピュータは内部的に全てのデータを2進数(ビット列)で扱います。ビット演算は、この2進数の各桁を直接操作する演算です。
論理演算
& | ^ ~
シフト演算
<< >>
何に使う? フラグ管理、マスク処理、高速な乗除算、ハードウェア制御、暗号処理など。組込み系・システムプログラミングでは必須です。
前提知識: 10進数の 12 は 2進数で 00001100。各桁が1か0かで値を表します。

AND, OR, XOR, NOT

各ビットに対して論理演算を行います。
AND ( & )
ABA&B
000
010
100
111
両方1のときだけ1
OR ( | )
ABA|B
000
011
101
111
どちらかが1なら1
XOR ( ^ )
ABA^B
000
011
101
110
異なるときだけ1
NOT ( ~ )
A~A
01
10
ビット反転

計算例

  0b11001010  (= 202)
& 0b10101010  (= 170)
-----------
  0b10001010  (= 138)  // 両方1のビットだけ残る

シフト演算 (<<, >>)

ビット列を左右に移動させる演算です。
左シフト ( << )
a << n = a × 2n
5 << 1 → 10(5×2)
5 << 3 → 40(5×8)
右シフト ( >> )
a >> n = a ÷ 2n(切り捨て)
40 >> 1 → 20(40÷2)
40 >> 3 → 5(40÷8)
// 5 を 2進数で見る
//   00000101 = 5
// 5 << 2
//   00010100 = 20  (5 × 4)
// 20 >> 1
//   00001010 = 10  (20 ÷ 2)
左シフト1回 = ×2、右シフト1回 = ÷2。乗除算より高速なので、パフォーマンスが重要な場面で使われます。

活用例

偶数・奇数の判定

if (n & 1) printf("奇数\n");
else        printf("偶数\n");
// 最下位ビットが1なら奇数、0なら偶数

フラグ管理

#define FLAG_READ   (1 << 0)  // 0001 = 1
#define FLAG_WRITE  (1 << 1)  // 0010 = 2
#define FLAG_EXEC   (1 << 2)  // 0100 = 4

int perm = 0;
perm |= FLAG_READ;              // フラグをON
perm |= FLAG_WRITE;             // フラグをON
if (perm & FLAG_READ) ...       // フラグをチェック
perm &= ~FLAG_WRITE;            // フラグをOFF
Linuxのファイルパーミッション(rwx = 読み書き実行)は、まさにこのビットフラグの仕組みです。

特定ビットの抽出(マスク)

int color = 0xFF5733;  // RGB色
int r = (color >> 16) & 0xFF;  // 255
int g = (color >> 8)  & 0xFF;  // 87
int b =  color        & 0xFF;  // 51

ビット演算計算機

2つの数値を入力して、各ビット演算の結果を確認しましょう。
「計算」を押してください

自分で書いてみよう ― ビット演算

ビット演算は「式の結果を2進数で確認する」練習が効果的です。最初は 0〜255 の範囲で考えると追いやすくなります。
課題1: 偶数・奇数判定
n & 1 を使って、入力された整数が偶数か奇数かを表示する。
課題2: フラグ管理
READ / WRITE / EXEC の3フラグを定義し、ON・OFF・チェックを行う関数を作る。
課題3: RGBの分解
0xRRGGBB 形式の整数から、シフトとマスクで R/G/B を取り出す。
間違えたら戻るページ: 2進数の見方が不安なら 第3回 変数、条件分岐は 第12回 if文、フラグをまとめるなら 第36回 構造体 も確認しましょう。

確認クイズ

0b1100 & 0b1010 の結果は?

0b1000 (8)
0b1110 (14)
0b0110 (6)
0b1010 (10)
解説: AND は両方1のビットだけ1。
1100 & 1010 → 1000 (= 8)。3ビット目だけ両方1。

n << 3 は n を何倍にする?

3倍
6倍
8倍
16倍
解説: 左シフト n 回 = ×2n
n << 3 = n × 23 = n × 8

関連する講座

入門編
第3回 変数
整数がメモリ上でビット列として扱われる前提を復習できます。
発展編
第36回 構造体(struct)
複数の状態をまとめる設計と、フラグ管理の使い分けを考えられます。
応用
画像処理
RGB値やマスク処理など、ビット演算の実用例につながります。
← 前の講座
第41回 確認問題(動的メモリ)
次の講座 →
第43回 データ構造入門

この講座の理解を深めるおすすめ書籍

サイトで動きを理解し、書籍で演習量を補うと効果的です

📘
苦しんで覚えるC言語
MMGames 著
初心者向けの定番入門書。
Amazonで見る
📗
新・明解C言語 入門編
柴田望洋 著
図解が豊富で演習問題も充実。
Amazonで見る
📙
プログラミング言語C 第2版
B.W.カーニハン, D.M.リッチー 著
通称K&R。C言語の原典。
Amazonで見る

※ 上記リンクはアフィリエイトリンクです。購入によりサイト運営を支援いただけます。

この記事をシェア
X(Twitter)でシェア Facebookでシェア LINEで送る はてブ