
~ 是按位取反,不是逻辑取反或负号
PHP 中的 ~ 对整数的**每一位二进制位做翻转**:0 变 1,1 变 0。它不关心数值大小或符号位含义,只机械地操作补码表示下的所有位(包括符号位)。很多人误以为 ~$x 等价于 -$x - 1,这在有符号整数补码体系下确实成立,但本质是结果,不是定义——真正发生的是位翻转。
常见错误现象:
• var_dump(~1); 输出 int(-2),而非 -1;
• 对无符号场景(比如处理 RGB 值、掩码)直接用 ~ 却没考虑 PHP 整数默认是有符号的,导致高位被解释为符号位,结果意外变负。
- PHP 整数在 64 位系统上通常是 64 位有符号整数,
~会翻转全部 64 位 - 如果只想翻转低 8 位(比如处理一个字节),必须手动屏蔽高位:
~$x & 0xFF -
~null或~false会先被转成0再取反,结果是-1,不是逻辑非
和 !、- 混用时行为完全不同
! 是布尔逻辑非,只关心“是否为 falsy”;- 是算术取负;而 ~ 是纯位操作。三者输入相同值,输出几乎总是不同。
使用场景差异:
• 判断变量是否为空?用 !;
• 取相反数?用 -;
• 构造掩码、翻转颜色通道、实现异或加密片段?才轮到 ~。
立即学习“PHP免费学习笔记(深入)”;
-
!5→false(因为 5 是 truthy) -
-5→-5 -
~5→-6(5 的二进制...0101→ 全位翻转得...1010,即 -6) - 对字符串或数组用
~会触发警告并转成0后再取反,结果恒为-1
实际用在掩码和位运算组合中才有意义
单独用 ~ 很少有意义,它真正发挥作用是在和 &、|、^ 配合构造位操作逻辑,比如清除某几位、生成反向掩码。
典型例子:清除一个整数的低 4 位(保留高 60 位):$x & ~0xF —— 这里 ~0xF(即 ~15)生成一个低 4 位全 0、其余位全 1 的掩码。
-
0xF是0b1111,~0xF在 64 位下是0xFFFFFFFFFFFFFFF0 - 务必注意:如果目标是 8 位环境(如单字节协议),要显式截断:
($x & ~0x0F) & 0xFF - PHP 不支持无符号右移
>>>,所以用~配合移位时需格外小心符号扩展问题
跨平台和大数时容易出错
PHP 的整数类型依赖底层平台和编译选项,~ 的结果在 32 位和 64 位环境可能不同,尤其当操作数接近 PHP_INT_MAX 时。
性能影响很小,但兼容性坑明显:
• ~PHP_INT_MAX 在 64 位系统上是 PHP_INT_MIN,但在某些嵌入式 PHP 移植版中可能溢出或截断;
• 如果从数据库读出的是 big integer 字符串,直接上 ~ 会先转成 float 或 int 导致精度丢失。
- 处理大于
PHP_INT_MAX的数,改用gmp_invert()或bcmod()配合位模拟 - 涉及网络协议或硬件交互时,优先用固定宽度类型(如
pack('C', ~$byte & 0xFF))避免平台差异 - 永远别假设
~$x === -$x - 1在所有边界条件下都成立——测试~PHP_INT_MIN就会发现它不满足这个等式
事情说清了就结束











