首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

STL bitset 巧用:以位掩碼優雅處理多條件組合判斷

     編輯:關於C語言

前言

處理「多條件組合」時,傳統做法常用 `int` 掩碼配合 `if-else` 鏈,條件一多代碼即變得冗長難維護。STL `std::bitset` 以編譯期固定大小的位陣列,提供直觀的「置位/測試/翻轉」語義,讓組合邏輯清晰且高效。

場景:二維圖形編輯器的點選判斷

需求:滑鼠點選時,同時在點陣列與線陣列中尋找距離最近且小於閾值的對象,產生四種組合情況:

  1. 點、線皆未命中
  2. 僅命中點
  3. 僅命中線
  4. 點、線皆命中 → 需比較距離遠近

傳統 int 掩碼寫法

UINT flag = 0;
if (hitPoint && !hitLine) flag = 1;
else if (!hitPoint && hitLine) flag = 2;
else if (hitPoint && hitLine) flag = 3;
// 後續仍需 switch(flag) 處理,易漏情況、難擴展

bitset 重構版

#include <bitset>
#include <vector>

struct Point { double x, y; };
struct Line  { Point p1, p2; };

std::bitset<2> hitMask;  // bit0:點 bit1:線

// 獨立判斷,互不干擾
if (findNearestPoint(mousePos, points, threshold)) hitMask.set(0);
if (findNearestLine (mousePos, lines,  threshold)) hitMask.set(1);

// 後續處理:語義清晰
if (hitMask.none()) {
    // 情況 1:都沒命中
} else if (hitMask.test(0) && !hitMask.test(1)) {
    // 情況 2:僅點
} else if (!hitMask.test(0) && hitMask.test(1)) {
    // 情況 3:僅線
} else { // hitMask == 0b11
    // 情況 4:都命中 → 比較距離
    double dPt = distToPoint(mousePos, nearestPoint);
    double dLn = distToLine  (mousePos, nearestLine);
    // 取較近者...
}

bitset 核心操作速查

操作語法說明
置位`bs.set(pos)` / `bs.set()`單位/全置 1
復位`bs.reset(pos)` / `bs.reset()`單位/全置 0
翻轉`bs.flip(pos)` / `bs.flip()`單位/全取反
測試`bs.test(pos)`返回 bool,越界拋出 `out_of_range`
任意/全為/全非`bs.any()` / `bs.all()` / `bs.none()`快速判斷整體狀態
計數`bs.count()`返回 1 的個數
轉字串`bs.to_string()`高位在前,如 "0011"
轉整數`bs.to_ulong()` / `to_ullong()`位數 ≤ 64 時可用
位運算`&` `|` `^` `~` `<<` `>>`支援標準位運算子

效能與適用性

  • 編譯期大小固定:`bitset` N 必須為常量表達式,適合已知上限的標誌位集合(如權限位、狀態機、特徵向量)。
  • 零開銷抽象:內部通常用 `unsigned long` 陣列,操作內聯為單條指令,效能等同手寫位運算。
  • 動態大小需求:改用 `std::vector` (特化位壓縮) 或 `boost::dynamic_bitset`。

擴展:MFC `UINT nFlags` 的 bitset 替代

MFC `OnMouseMove(UINT nFlags, CPoint)` 中 `nFlags` 即為位掩碼(`MK_LBUTTON`、`MK_CONTROL` 等)。若自行設計訊息系統,可用 `bitset<32>` 替代,獲得型別安全與可讀性:

enum MouseFlag { LBUTTON=0, RBUTTON=1, SHIFT=2, CTRL=3, MIDDLE=4 };
std::bitset<32> flags;
flags.set(LBUTTON);  // 清楚表達意圖
if (flags.test(CTRL) && flags.test(LBUTTON)) { /* Ctrl+左鍵 */ }
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved