コードを書き始めて間もないころは、単純な処理しか書いていなかったので状態管理についてはあんまり意識していなかったと思います。
しかし、どんどんコードを書いていくうちに
「うわ~、この処理は○○で□□な状態において、△△を満たすならば実行したいな~」
みたいに、複数の状態を見て処理フローを分岐させることもあると思います。
そんなときに、複数のbool
を並べて
if (isLoggedIn && isEditing && !isSaved) { ... }
みたいに書くのは、面倒だし分かりづらい。。。
そこで登場するのが、今回紹介する ビット演算による状態管理 です。一つの変数で複数の状態を管理できて、かつ、分かりやすい。状態管理スキルを一つ次のステージに進めるためにも、知っておいて損はないと思います。(本記事は初心者が勉強のために書いています。不正確な点等があれば教えてください。)
ビット演算とは?
ビット演算とは、コンピュータで使われる2進数のビット単位での演算のことです。
簡単に言うと、数字の0や1を直接操作する方法です。
例えば、通常の足し算や掛け算では「数」を扱いますが、ビット演算では「ビット」を直接操作します。
これによって、非常に高速で効率的な計算が可能になります。まずは、基本的な演算について確認して行きましょう。
具体的なビット演算の種類
主なビット演算は以下の4つです:
1.AND 演算 (&)
2つのビットが両方とも1のときだけ、結果が1になります。
例:1010 & 1100 = 1000
(ビットごとに「1かどうか」をチェック)
2.OR 演算 (|)
2つのビットのどちらか一方でも1のとき、結果が1になります。
例:1010 | 1100 = 1110
(少しでも1があれば結果は1)
3.XOR 演算 (^)
2つのビットが異なるときだけ、結果が1になります(異なるときに1)。
例:1010 ^ 1100 = 0110
(違うビットだけ1)
4.NOT 演算 (~)
1ビットを反転させます(0は1に、1は0に)。
例:~1010 = 0101
(すべてのビットを反転)
今回のビット演算による状態管理では、主に1番と2番のAND演算とOR演算を使用します。
ビット演算による状態管理
C言語では、int
型の変数を使用することで、最大32個の状態管理フラグを立てることが出来ます。
↓フラグの定義例
# define FLAG_ACTIVE 0b00000001
# define FLAG_EDITING 0b00000010
# define FLAG_HIDDEN 0b00000100
このようにビットごとに状態を割り当てておけば、あとはビット演算で自在に管理できます。別の書き方として、以下のように書くこともできます。
#define FLAG_ACTIVE (1 << 0) // 0b00000001
#define FLAG_EDITING (1 << 1) // 0b00000010
#define FLAG_HIDDEN (1 << 2) // 0b00000100
ここで使っている (1 << n)
は、「1をnビット左にずらす」という意味で、
1 << 0
→ 0b00000001
1 << 1
→ 0b00000010
1 << 2
→ 0b00000100
というように、1つのビットだけが1になった値を生成しています。
使用例
①状態を設定する
まずは、状態をONにするためには、OR
演算(|=)
を使用します。
int flag = 0; // すべての状態がOFF
flag |= FLAG_ACTIVE; // アクティブ状態をON
flag |= FLAG_EDITING; // 編集状態もON
こうすると、flag には 0b00000011
(=3)が格納されます。
つまり「アクティブ」と「編集中」の両方の状態がONになっている状態です。
②状態をチェックする
状態がONかどうかをチェックしたいときは、AND演算(&)を使います。
int flag = 0; // 最初は全部OFF
// 状態を追加(例:アクティブ & 編集中にする)
flag |= FLAG_ACTIVE;
flag |= FLAG_EDITING;
// 状態を確認(例:アクティブか?)
if (flag & FLAG_ACTIVE) {
printf("アクティブです!\n");
}
③状態をOFFにする
特定の状態だけオフにしたい場合は、AND
とNOT
を組合わせます。
flag &= ~FLAG_EDITING; // 編集状態をOFF
このように、ビット演算を駆使して状態を管理することで、どの状態がONかOFFか分かりやすく、変数も増えないというメリットがあります!是非有効活用してみてください。