PHP 位运算:移位、奇偶判断与权限标记

位运算适合处理二进制标记,例如把“读取、编辑、删除”几项权限存放在一个整数里。它也能表达某些乘除关系,但不应该把“更底层”直接理解为“在 PHP 中必然更快”。

本文示例都使用整数;PHP 的某些位运算在两个操作数都是字符串时会按字节处理,不要与下面的整数逻辑混用。

一、左移与右移

var_dump(3 << 4);  // int(48)
var_dump(32 >> 3); // int(4)

对非负整数,在结果不溢出、移位数合法的范围内,左移 n 位相当于乘以 2 的 n 次方。非负整数右移 n 位相当于除以 2 的 n 次方并向下取整。

这不适用于所有除法语义:

var_dump(5 / 2);         // float(2.5)
var_dump(5 >> 1); // int(2)
var_dump(intdiv(-3, 2)); // int(-1),向零截断
var_dump(-3 >> 1); // int(-2),算术右移保留符号

PHP 的整数宽度依赖平台,可以查看 PHP_INT_SIZE 和 PHP_INT_MAX。1 << 32 不能无条件等同于 pow(2, 32):常见 64 位平台能表示这个移位结果,32 位平台则不能;移位还可能丢弃高位、改变符号,而 pow() 有自己的数值及类型规则。

位移不能直接求平方根。用移位表达整数乘除也不保证性能更好,实际耗时还取决于 PHP 版本、JIT、类型转换和上下文。业务代码优先写清楚运算含义,有性能瓶颈时再测量。语义和平台限制见 PHP 位运算文档。

二、与、或、异或、取反

运算符 含义 对整数位的作用
& 按位与 两边都是 1,该位才是 1
`\ ` 按位或 任一边是 1,该位就是 1
^ 按位异或 两边不同,该位是 1
~ 按位取反 翻转每一位,包含整数符号相关的位

判断奇偶

$number = 7;
$isOdd = (($number & 1) === 1);
var_dump($isOdd); // bool(true)

最低位为 1 表示奇数,为 0 表示偶数。这里显式加括号,避免把按位运算和比较运算的优先级记混。按位或 | 与逻辑 or、|| 不是同一种操作。

设置与清除最低位

var_dump(6 | 1);  // int(7),最低位设为 1
var_dump(7 & ~1); // int(6),最低位清零

对非负整数,清除最低位得到不大于原数的相邻偶数,不能笼统称为“最接近的偶数”:例如 7 到 6 和 8 的距离相同。

三、用不同的位记录权限

每一项独立标记占用一个不同的二进制位:

const READ = 1 << 0;   // 1
const EDIT = 1 << 1; // 2
const DELETE = 1 << 2; // 4

$permissions = READ | EDIT;

$canRead = (($permissions & READ) === READ);
$canReadAndEdit = (($permissions & (READ | EDIT)) === (READ | EDIT));
$hasAny = (($permissions & (EDIT | DELETE)) !== 0);

$permissions |= DELETE; // 添加删除标记
$permissions &= ~EDIT; // 清除编辑标记
$permissions ^= READ; // 切换读取标记

检查“全部具备”和“任意具备”的条件不同。异或是切换,不是保证添加;重复执行两次又会恢复原状态。添加标记用或、清除标记用与配合取反,意图更明确。

位掩码只是权限数据的表示形式,不能替代服务端鉴权。真正允许用户操作某条记录之前,还需要核对身份、角色、资源归属等业务规则。位数也受整数宽度限制,不要无限增加标记。


文章作者: Crazy Boy
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Crazy Boy !
赏

留言

想法、疑问或勘误,都可以写在这里。留言会公开显示。

正在准备留言区…

 上一篇
密码安全:弱密码、撞库与账号防护 密码安全:弱密码、撞库与账号防护
密码安全不能只看有没有大写字母、数字和符号。一个看起来“符合规则”的口令,如果容易猜到、曾经泄露,或者在多个网站重复使用,同样可能让账号失守。 从后端开发的角度,我更愿意把它分成两件事:用户如何选择和保管密码,系统如何验证、存储并保护登录过
2026-10-19
下一篇 
PHP 变量与类型转换:中文变量、字符串与小数末尾的零 PHP 变量与类型转换:中文变量、字符串与小数末尾的零
写 PHP 时,一些很短的语句也值得留一份说明:变量能不能用中文,三种转字符串的方式有什么区别,以及怎样去掉小数末尾的零。它们都能快速写出来,但处理的数据不同,边界也不同。 一、PHP 可以使用中文变量名吗? 可以。例如将文件保存为 UTF
2026-10-19