权限系统需用2的整数次幂表示权限,通过位运算&、|、&~实现判断、叠加与清除;状态标记、奇偶判断、移位等场景同理,须注意类型转换和符号扩展问题。

权限系统用 & 判断、| 合并、& ~ 清除
权限值必须是 2 的整数次幂(1、2、4、8…),这样每个权限独占一个二进制位。常见错误是把权限当普通数字加减,比如 7 = 4 + 2 + 1 看似合理,但本质是 4 | 2 | 1 ——只有用位或才能确保不冲突。
- 检查权限:
$userPerm & READ非零即拥有;别写if ($userPerm and READ),那是逻辑判断,不是位判断 - 叠加权限:
$userPerm |= WRITE,等价于$userPerm = $userPerm | WRITE - 撤回权限:
$userPerm &= ~EXECUTE,~EXECUTE把 EXECUTE 对应位变 0、其余变 1,再与原值做 & 就清除了该位 - 数据库里存一个整数就够了,不用为每种权限建字段;查询时也只需
WHERE perm & ?,比 JSON 或逗号分隔快得多
状态标记用单个整数代替多个布尔字段
比如广告投放系统要支持「仅登录用户」「仅 VIP」「30 天内注册」「30 天未登录」等条件,每加一种就加一个 TINYINT 字段?没必要。用一个 INT 字段存位组合更轻量、更易扩展。
- 定义常量:
define('COND_LOGGED', 1); define('COND_VIP', 32); define('COND_NEW_USER', 4);(注意:幂次别重复) - 查广告:
SELECT * FROM ads WHERE display = 1 AND bit_condition & 33表示“同时满足 COND_LOGGED 和 COND_VIP” - PHP 层组合:
$cond = COND_LOGGED | COND_VIP;,直接传整数进 SQL,避免字符串拼接或 IN 查询 - 别在 PHP 里用
in_array()去匹配一堆状态码——那是在数组里线性扫,而&是 CPU 单指令完成
& 1 判断奇偶、^ 1 翻转最低位
这是最轻量级但高频的位操作,比取模 % 2 或布尔取反快一个数量级,尤其在循环中处理大量数值时差异明显。
- 判断奇偶:
if ($n & 1) { /* 奇数 */ },因为偶数最低位必为 0,奇数必为 1 - 翻转奇偶性:
$n ^= 1,^是异或,相同为 0、不同为 1;所以5 ^ 1 → 4,4 ^ 1 → 5 - 清零最低位(向下对齐到偶数):
$n & ~1,~1在 64 位下是全 1 除最低位为 0,& 后自然抹掉最低位 - 别对浮点数或字符串用这些操作——
'5' & 1会静默转成0 & 1 = 0,结果永远错
移位运算慎用于算术,优先考虑无符号语义
和 <code>>> 不是万能乘除法。PHP 整数有符号,负数右移会补符号位,-1 >> 1 还是 -1,不符合数学直觉;左移超限还会溢出变负。
立即学习“PHP免费学习笔记(深入)”;
- 非负数场景可放心用:
$x ≡ <code>$x * 8,$x >> 2≡(int)($x / 4) - 需要无符号右移?用
($x >> $n) & 0x7FFFFFFF(32 位)或($x >> $n) & 0x7FFFFFFFFFFFFFFF(64 位)截断符号位 - 位数不能 ≥ 当前平台整数位宽:
1 >> 64在 64 位 PHP 8+ 中抛ValueError - IP 转整数等底层操作常用移位,但务必确认输入是
int类型,ip2long()返回值可能为负,需先& 0xFFFFFFFF归一化
实际项目里最容易被忽略的,是类型隐式转换和符号扩展问题——& 操作前没 cast 成 int,或者对负数移位却期望得到数学除法结果。这类 bug 往往只在特定数据下暴露,调试成本远高于写的时候多加一行 (int) 强转。



















