php位运算符有&(按位与,用于权限校验)、|(按位或,用于权限叠加)、^(按位异或,用于位翻转)、~(按位取反,注意符号扩展)、(右移,算术右移)。

PHP位运算符有哪些,各自干啥用
PHP的位运算符就是直接对整数的二进制位做操作,不是数学计算,是“开关式”控制。常见的有 &(与)、|(或)、^(异或)、~(取反)、(左移)、<code>>>(右移)。
它们不处理浮点数,传入浮点会自动转成整型(截断小数),但更常见的是传错类型导致结果诡异——比如传了个字符串 "15",PHP会尝试转成 15;但传 "0x1F" 就变成 0,因为强制整型转换不解析十六进制字符串。
-
&常用于权限校验:比如用户权限是$userPerm = 5(二进制101),要判断是否含“删除”位(假设第2位,即4),写$userPerm & 4,非零就表示有 -
|用于叠加权限:$newPerm = $oldPerm | 8表示加“导出”权限 -
^可翻转特定位:$flags ^= 1把最低位取反,适合开关切换 -
~注意符号扩展:在32位系统上~0是-1(全1补码),不是4294967295;想得无符号效果得用~$x & 0xFFFFFFFF
PHP整型位移怎么写才不出错
左移 和右移 <code>>> 看似简单,但PHP里有两个大坑:一是位移位数超长整型宽度时行为未定义(不同版本/平台结果可能不同),二是右移对负数执行算术右移(保留符号位),不是逻辑右移。
比如 -8 >> 1 在大多数PHP环境中得到 -4,而不是 2147483644(如果按无符号理解)。你不能靠它来“补零右移”。
立即学习“PHP免费学习笔记(深入)”;
- 位移位数必须是非负整数,否则会警告并当作
0处理;5 不报错但结果等于 <code>5 - 位移位数超过整型位宽(如64位系统上移 >63)会导致结果为
0或溢出,PHP不会抛异常,只静默截断 - 需要逻辑右移时,得手动屏蔽符号位:
($x >> $n) & ~(~0 ,或者更稳妥地转成无符号上下文再操作 - 实际项目中,除非明确需要位级优化(如协议解析、加密算法),否则别用位移代替乘除——
$x * 2更可读,且PHP 8+ JIT下性能差异几乎为零
为什么 var_dump(1
因为PHP整型底层依赖C的 long 类型,而 1 在32位系统上会溢出符号位,变成负数(<code>-2147483648),64位系统则仍是正数(2147483648)。这不是bug,是整型表示范围决定的。
这意味着靠位移构造掩码时,跨平台代码极易出错。比如想定义一个“第32位为1”的标志,在32位环境根本存不住。
- 避免硬编码高位偏移,改用
1 且确保 <code>$i - 需要固定宽度位模式(如32位掩码),显式用
0xFFFFFFFF而不是(1 (后者在32位PHP会溢出) - 调试时用
sprintf('%032b', $x)查看二进制,比var_dump直观得多 - Composer包如
symfony/polyfill-intl-idn里有大量位运算兼容处理,可以参考其对PHP_INT_SIZE的守卫写法
位运算在真实项目里该不该用
该用,但只在它真正解决问题的地方用:权限位图、状态压缩、网络字节序转换、哈希混淆、某些FFI或扩展开发场景。其他时候,可读性和可维护性优先。
最容易被忽略的一点是:PHP的整型在64位系统上默认是有符号的,但很多位运算逻辑隐含“无符号”假设。一旦数据来自外部(如数据库字段定义为 UNSIGNED INT),PHP读出来仍是带符号整型,直接参与位运算可能翻车。
- 从MySQL读
UNSIGNED INT到PHP,值大于2147483647时在32位PHP会变负数,此时做&操作结果完全不可控 - 用PDO时开启
PDO::ATTR_EMULATE_PREPARES = false并配合PDO::MYSQL_ATTR_USE_BUFFERED_QUERY,能缓解部分类型失真,但最稳方案是统一用字符串接收再gmp_init()处理 - 单元测试必须覆盖边界值:
0、1、PHP_INT_MAX、PHP_INT_MIN、PHP_INT_MAX + 1(会转float)
事情说清了就结束










