【C++】std::bitsetでビット操作を簡単に行う

ビット操作はプログラミングで良く使われるテクニックですが、直接ビットを操作するコードは非常に複雑になりがちで、バグの原因にもなります。

ビット操作を簡潔に、安全に行いたい。そこで登場するのが「std::bitset」。

std::bitsetは、固定長のビット列を表現するクラスで、ビットごとのセット、リセット、反転、論理演算などを簡単、安全に行うことができます。

今回は、std::bitsetの基本的な使い方から、実際のプログラムでの使い方を紹介します。

std::bitsetの概要

std::bitsetとは、ビット単位のデータを簡潔に管理・操作することができるクラスです。

固定長のビット列を管理し、セット、リセット、反転といったビット操作やビット演算が簡単に行えます。

また、文字列や整数を指定してビット列を初期化することや、ビット列を文字列や整数に変換することもできます。

std::bitsetの使い方

std::bitsetの使い方です。

宣言と初期化

std::bitsetの基本的な宣言方法と初期化方法です。

#include <bitset>
#include <iostream>

int main() {
  std::bitset<8> bit1;            // 8bitのbitsetを作成
  std::bitset<8> bit2(10);        // 整数値10からbitsetを作成
  std::bitset<8> bit3("101010");  // 文字列からbitsetを作成

  std::cout << bit1 << "\n" << bit2 << "\n" << bit3 << std::endl;

  return 0;
}
【出力結果】
00000000
00001010
00101010

ビット操作

std::bitsetのビット操作方法です。ビットのオン/オフ、反転を行います。

#include <bitset>
#include <iostream>

int main() {
  std::bitset<8> bits(0b1110);
  bits.set(0);        // ビット0を1にする
  bits.flip(1);       // ビット1を反転する
  bits.reset(2);      // ビット2を0にする
  std::cout << bits;

  return 0;
}
【出力結果】
00001001

ビット演算

std::bitsetのビット演算方法です。

ビットの状態を操作・比較し、フラグ管理やマスク操作の様な場面で使用されます。

#include <bitset>
#include <iostream>

int main() {
  std::bitset<8> a("1100");
  std::bitset<8> b("1010");
  std::cout << (a & b) << std::endl;  // AND演算
  std::cout << (a | b) << std::endl;  // OR演算
  std::cout << (a ^ b) << std::endl;  // XOR演算

  return 0;
}
【出力結果】
00001000
00001110
00000110

AND演算子は、対応するビットが両方とも1であれば1になり、それ以外は0となります。
OR演算子は、対応するビットのどちらかが1であれば1になります。
XOR演算子は、対応するビットが異なれば1になり、同じであれば0となります。

std::bitsetを使ってフラグ管理をする

各ビットに、「毒」「麻痺」「睡眠」などの状態異常を対応させ、それらをstd::bitsetで管理するサンプルです。

#include <bitset>
#include <string>
#include <iostream>

// キャラクターの状態異常を表すフラグの定義
const int POISON = 0;       // 毒
const int PARALYSIS = 1;    // 麻痺
const int SLEEP = 2;        // 眠り
const int CONFUSION = 3;    // 混乱
const int SILENCE = 4;      // 沈黙

// 状態を出力する関数
std::string getState(std::bitset<8> state) {
  std::string res = "";
  if (state.test(POISON)) {
      res.append("毒 ");
  }
  if (state.test(PARALYSIS)) {
      res.append("麻痺 ");
  }
  if (state.test(SLEEP)) {
      res.append("睡眠 ");
  }
  if (state.test(CONFUSION)) {
      res.append("混乱 ");
  }
  if (state.test(SILENCE)) {
      res.append("沈黙 ");
  }
  return res;
}

int main()
{

  std::bitset<8> state;  // キャラクターの状態を管理する8ビットのビットセット
  
  // 状態異常の設定
  // 状態異常の設定
  state.set(POISON);    // 毒
  state.set(SLEEP);  // 混乱

  // 状態の確認
  std::cout << "現在のキャラクターの状態: ";
  std::cout << getState(state) << std::endl;

  // 状態の変更
  std::cout << "\n敵の攻撃により、麻痺になった...\n";
  state.set(PARALYSIS);  // 麻痺にフラグを変更

  // 再度状態を確認
  std::cout << "\n現在のキャラクターの状態: ";
  std::cout << getState(state) << std::endl;
  std::cout << "現在のビットセットの状態: " << state << std::endl;

  // 状態のリセット
  std::cout << "\nキャラクターが眠りから覚めた...\n";
  state.reset(SLEEP);  // 睡眠のフラグをリセット

  // 再度状態を確認
  std::cout << "\n現在のキャラクターの状態: ";
  std::cout << getState(state) << std::endl;
  std::cout << "現在のビットセットの状態: " << state << std::endl;

  // 状態異常が発生しているか確認する
  std::cout << "\n状態異常の有無: ";
  std::cout << (state.any() ? "有り" : "無し") << std::endl;

  // 状態異常が全て解消
  std::cout << "\n全ての状態異常が解消された...\n";
  state.reset();

  // 再度状態を確認
  std::cout << "\n現在のキャラクターの状態: ";
  std::cout << getState(state) << std::endl;
  std::cout << "現在のビットセットの状態: " << state << std::endl;

  return 0;
}

【出力結果】
現在のキャラクターの状態: 毒 睡眠 

敵の攻撃により、麻痺になった...

現在のキャラクターの状態: 毒 麻痺 睡眠 
現在のビットセットの状態: 00000111

キャラクターが眠りから覚めた...

現在のキャラクターの状態: 毒 麻痺 
現在のビットセットの状態: 00000011

状態異常の有無: 有り

全ての状態異常が解消された...

現在のキャラクターの状態: 
現在のビットセットの状態: 00000000
前

RPGの状態異常のように、複数の異なる状態が同時に発生する場合の状態管理を効率的に行うことができます。

std::bitsetのまとめ

std::bitsetを使えば、ビットごとの操作を簡単なメソッドで行えるため、直接ビット演算子を使うよりも可読性が上がります。

また、std::bitsetはビット数を定義して使用するため、意図した範囲内でのみ操作が行われ、予期せぬオーバーフローや型の不一致によるエラーは防げます。

しかし、std::bitsetは、固定サイズのビット列しか扱えないため、ビット数が変更する場合や、可変長のデータをビット列で管理したい場合には使うことができません。

その場合は、std::vector<bool>などを使う必要がありますが、std::bitsetほど効率的ではありません。

std::bitsetを使って効率的なビット操作を取り入れて、よりスマートなC++プログラムを作成しましょう。

スポンサーリンク

  • この記事を書いた人

まさじぃ

ダメプログラマ歴17年です。 プログラミング関連の事や、 自分で使って良かったもの等の紹介をメインにやっています。

-プログラミング
-