权限位必须用2的幂次(如1、2、4、8)定义,即每位仅一个二进制位为1,避免重叠;错误做法是用连续整数(如3=11₂),会导致权限误判。

权限位怎么定义才不冲突
用整数的每一位代表一种权限,必须确保每个权限对应唯一且互不重叠的二进制位。常见错误是直接用 1、2、3 这类连续整数当权限值——3 的二进制是 11,它同时“包含”读和写,会导致误判。
正确做法是用左移操作定义:
const int PERMISSION_READ = 1 → <code>1(二进制 001)
const int PERMISSION_WRITE = 1 → <code>2(二进制 010)
const int PERMISSION_DELETE = 1 → <code>4(二进制 100)
这样任意组合(如 READ | WRITE)都是唯一可拆解的。
如何检查用户是否拥有某权限
用按位与(&)判断:只要结果非零,就说明该位被置起。
别写成 if (user_perms == PERMISSION_READ) —— 这要求用户**只有读权限**,实际中用户往往有多个权限组合。
- ✅ 正确:
if (user_perms & PERMISSION_READ) - ❌ 错误:
if (user_perms == PERMISSION_READ) - ⚠️ 注意:
user_perms是 int 类型,不要用bool存储,否则会丢失其他位信息
如何增删权限(不是覆盖)
权限是叠加的,不是替换。增加用按位或(|=),删除用按位与加取反(&= ~)。
示例:
int user_perms = PERMISSION_READ; user_perms |= PERMISSION_WRITE; // 加写权限 → 值变为 3(011) user_perms &= ~PERMISSION_READ; // 删读权限 → 值变为 2(010)
关键点:
-
~PERMISSION_READ是对单个权限取反,得到一个除该位外全为 1 的掩码 - 不能用
user_perms = user_perms - PERMISSION_READ—— 如果用户没有该权限,减法会破坏其他位(比如3 - 1 = 2看似对,但2 - 1 = 1就错了) - 如果权限值用
unsigned int或uint32_t更安全,避免符号位干扰
实际使用时容易忽略的边界
位运算本身很快,但权限管理真正复杂的地方不在运算,而在语义和生命周期。
- 权限常量建议统一定义在头文件里,避免不同模块用不同数值(比如有人写
1 当 delete) - 数据库存权限字段时,推荐存整数而非字符串枚举,但要确认 ORM 或序列化库支持整型映射(如 SQLite 直接存 int 没问题,JSON 序列化也无压力)
- 调试时打印权限值没用,应转换为可读形式:
printf("perms: %s%s%s", (p&READ)?"R":"", (p&WRITE)?"W":"", (p&DELETE)?"D":""); - 如果未来要扩展到 32 种权限,
int可能不够(取决于平台),改用uint64_t并配合静态断言更稳妥
位运算只是工具,权限逻辑一旦涉及角色继承、临时授权、过期时间,就得跳出纯位操作,引入专门的数据结构了。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











