
位运算符在 PHP 中的实际用途是什么
PHP 的位运算符不是用来炫技的,而是解决特定问题的工具:权限控制、状态标记、网络协议解析、图像像素处理这些场景里,用 &、|、^、~、、<code>>> 比字符串或数组更省空间、更快。它们直接操作整数的二进制位,所以输入必须是整数(int),浮点数、字符串、null 会被静默转成 0,容易出错。
常见错误现象:echo '12' & '3'; 输出 0 —— 因为字符串被转成 0 再运算;echo 12 & '3'; 同样是 0;只有 12 & 3 才是预期的 0(1100 & 0011 = 0000)。
- 权限系统常用
1 (1)、<code>1 (2)、<code>1 (4)定义 READ/WRITE/EXECUTE - 判断是否拥有某权限:用
&,如$userPerm & READ - 添加权限:用
|,如$userPerm |= WRITE - 移除权限:用
& ~,如$userPerm &= ~EXECUTE
为什么 & 和 and 结果不同
这是最容易踩的坑:& 是位运算符,and 是逻辑运算符,优先级完全不同。PHP 中 and 优先级比赋值 = 还低,而 & 优先级高于 =。
示例:$a = 5 & 3; → 正确计算为 $a = 1;但 $a = 5 and 3; → 先执行 $a = 5(返回 true),再执行 true and 3(返回 true),但 $a 仍是 5,整个表达式结果却被丢弃。
立即学习“PHP免费学习笔记(深入)”;
- 永远用
&做位判断,别用and替代 - 调试时加括号不保险:
($a = 5) and 3依然不是位运算 - 检查权限组合是否生效?直接输出
var_dump($perm & FLAG_A),别用if ($perm and FLAG_A)
和 <code>>> 移位要注意符号和溢出
左移 相当于乘以 2 的 n 次方,右移 <code>>> 相当于除以 2 的 n 次方并向下取整——但仅对非负数成立。PHP 的整数是有符号的(通常 64 位),右移负数会做算术右移(高位补 1),结果不符合直觉。
示例:echo -8 >> 1; 输出 -4(正常),但 echo -1 >> 1; 输出 -1(因为全 1 的补码右移还是全 1);而 echo 0x80000000 >> 1; 在 32 位系统上可能变成负数,64 位上也可能因符号位触发扩展。
- 只对已知非负整数使用移位,否则先用
abs()或& 0xffffffff截断 - 移位位数不能为负,也不能 ≥ 整数位宽(如 64 位系统上不能
>>64),否则结果为0(PHP 8+ 报ValueError) - 需要无符号右移?用
($x >> $n) & ~(~0 或改用 <code>gmp扩展
位运算和类型转换的隐式陷阱
PHP 不强制类型声明,但位运算要求操作数是整型。一旦传入 float、string、bool,就会触发隐式转换,且规则不直观:
echo 12.9 & 7; → 12 & 7 = 4(float 转 int 是截断,不是四舍五入);echo '12' & '7'; → 0 & 0 = 0(字符串转整数失败时为 0);echo true & false; → 1 & 0 = 0(bool 转整数是 1/0)。
- 入库前或函数入口加
assert(is_int($x) && is_int($y))或用严格类型声明function foo(int $a, int $b): int - 从
$_GET或数据库读来的数字,务必用(int)强转,别依赖自动转换 - 用
var_dump(gettype($x), $x)确认真实类型,比echo更可靠
位运算本身很快,但类型混乱会让结果不可预测。真正难的不是记住 ^ 是异或,而是确保参与运算的每个值,从源头开始就是干净的整数。










