news 2026/6/2 20:07:55

【位运算符】爆肝整理!C++位运算从入门到精通(面试必背),原反补+奇技淫巧,手撕算法题就靠它!

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【位运算符】爆肝整理!C++位运算从入门到精通(面试必背),原反补+奇技淫巧,手撕算法题就靠它!

C++ 位运算符全扩展技巧(面试必背)






文章目录

  • C++ 位运算符全扩展技巧(面试必背)
    • @[toc]
    • 一、基础位运算符回顾
      • 原码,反码,补码
      • 1. 对于**正数**和**+0**
    • 二、⭐ 判断
      • 1.判断奇偶
      • 2. 判断 2 的幂
      • 3. 判断 符号是否相同
      • 4. 判断第 n 位是否为 1(n 从 0 开始计数)
    • 三、⭐ 修改
      • 1. 置 1
      • 2. 置 0
      • 3. 翻转
      • 4. ‼️ 把最低位的 1置0
      • 5. 保留最低位的 1,其他位全部清零
        • 为什么必须用 long long?
      • 6. ‼️交换两个整数
    • 四、数学
      • 1. 乘 2 的 n 次方
      • 2. 除以 2 的 n 次方(仅适用于正数)
      • 3. 对 2 的 n 次方取模
      • 4. 求整数的绝对值(不用 if 分支)
    • 五、算法类技巧(面试高频)
      • 1. 二进制中 1 的个数
      • 2. 加法
      • 3. 缺失的数字
      • 4. 只出现一次的数字系列
    • 七、重要注意事项(必看坑)
    • 面试必背速查表





一、基础位运算符回顾

原码,反码,补码

数值原码反码补码
+50000 01010000 0101(正数与原码相同)0000 0101(正数与原码相同)
-51000 0101(最高位1表示负,和+5同)1111 1010(符号位不变,其余位取反)1111 1011(反码 + 1)
00000 00001000 0000(存在+0和-0)0000 00001111 1111(同样两个0)0000 0000(唯一零,-0的补码也是0)





1. 对于正数和**+0**

  • 原码 = 反码 = 补码(符号位为0,数值位不变)。

内存中,数字以32位数存储

原反补的关系

原码:二进制数字,前面加上1(负数)或0(整数)

反码:原码除了表示正负号的第一位不变,其他都取反

补码:反码+1➡️内存中储存并使用的形式**(-1是全1)**

对于负数:补码和原码相互是取反加一的关系,当然,第一位代表符号,不看

  1. 有符号整型(signed int)
    1. 整数:原反补相同
    2. 负数:原反补都不同
  2. 无符号整型(unsigned int):都相同

6的原码,反码,补码:000000000000000000000110

3的原码,反码,补码:000000000000000000000011

-5的原码:100000000000000000000101

-5的反码:111111111111111111111010

-5的补码:111111111111111111111011




运算符名称运算规则例子(十进制)例子(二进制)
&按位与全 1 为 1,有 0 为 06 & 3 = 2110 & 011 = 010
``按位或有 1 为 1,全 0 为 0`6
^按位异或相同为 0,相异为 16 ^ 3 = 5110 ^ 011 = 101
~按位取反0 变 1,1 变 0~6 = -7补码表示
<<左移所有位左移 n 位,低位补 06 << 1 = 12110 << 1 = 1100
>>右移所有位右移 n 位,高位补符号位6 >> 1 = 3110 >> 1 = 011






二、⭐ 判断






1.判断奇偶

  • 判断最后一位是0是1
boolis_odd(intx){returnx&1;}





2. 判断 2 的幂

  • 判断一个数的二进制位是否只有一个1
boolis_power_of_two(intx){returnx>0&&(x&(x-1))==0;}
  • 例子:8 & 7 = 0(是),6 & 5 = 4(不是)
  • 原理:2 的幂的二进制只有一个 1,减 1 后所有低位都变成 1,与运算结果为 0
  • 对应 LeetCode:231. 2 的幂





3. 判断 符号是否相同

  • 整体数字异或,只看结果的符号位:同0(正数)异1(负数)
boolsame_sign(intx,inty){return(x^y)>=0;}
  • 例子:3 ^ 5 = 6 >= 0(同号),3 ^ (-5) = -8 < 0(异号)





4. 判断第 n 位是否为 1(n 从 0 开始计数)

boolis_bit_set(intx,intn){return(x>>n)&1;}






三、⭐ 修改

1. 置 1

intset_bit(intx,intn){returnx|(1<<n);}
  • 例子:set_bit(4, 1) = 6(100 | 010 = 110)





2. 置 0

intclear_bit(intx,intn){returnx&~(1<<n);}
  • 例子:clear_bit(6, 1) = 4(110 & 101 = 100)





3. 翻转

  • 异或:同0异1
int toggle_bit(int x, int n) { return x ^ (1 << n); }
  • 例子:toggle_bit(6, 0) = 7(110 ^ 001 = 111)





4. ‼️ 把最低位的 1置0

intclear_lowest_one(intx){returnx&(x-1);}
  • 例子:6 & 5 = 4(110 → 100,最低位的 1 被清零)

  • 核心用途:

    • 统计二进制中 1 的个数
    • 判断 2 的幂
    • 求最大公约数





5. 保留最低位的 1,其他位全部清零

// 注意:用long long避免INT_MIN溢出longlongget_lowest_one(longlongx){returnx&(-x);}



例子 1:正数 6(二进制 0110)

x = 6 → 0000 0110 (补码:~6 + 1 = 1111 1001 + 1 = 1111 1010) (-x补码: ~(-6) + 1 = ~(1000 0110)+1 = 1111 1001 + 1 = 1111 1010) -x = -6 → 1111 1010 x & (-x) → 0000 0010 = 2

✅ 结果是 2,正好是 6 最低位的 1(第 1 位)

x = 12 → 0000 1100 (-x补码: ~(-12) + 1 = ~(1000 1100)+1 = 1111 0011 + 1 = 1111 0100) -x = -12 → 1111 0100 x & (-x) → 0000 0100 = 4

✅ 结果是 4,正好是 12 最低位的 1(第 2 位)。




x = -6 → 1111 1010 (-x补码: 就是6 ) -x = 6 → 0000 0110 x & (-x) → 0000 0010 = 2

✅ 结果还是 2,和正数 6 一样,因为最低位的 1 的位置没变。

  • 例子:6 & (-6) = 2(110 → 010)





为什么必须用 long long?

(INT_MIN 的坑)

int的最小值是INT_MIN = -2147483648,它的二进制是1000 0000 ... 0000(只有最高位是 1)

x = INT_MIN → 1000 0000 ... 0000 -x = 2147483648 → 这个数超过了int的最大值(2147483647),溢出了!

溢出在 C++ 里是未定义行为,不同编译器结果不一样。用long long就不会有这个问题,因为 long long 的范围大得多。






6. ‼️交换两个整数

voidswap(int&a,int&b){a^=b;b^=a;//相当于b ^ a ^ b结果是 aa^=b;//相当于a ^ a ^ b结果是 b}






四、数学

1. 乘 2 的 n 次方

intmultiply_by_power_of_two(intx,intn){returnx<<n;}
  • 例子:3 << 2 = 12(3 * 4 = 12)





2. 除以 2 的 n 次方(仅适用于正数)

intdivide_by_power_of_two(intx,intn){returnx>>n;}
  • 例子:12 >> 2 = 3(12 / 4 = 3)
  • 坑:负数右移是算术右移,结果和除法不同(-5 >> 1 = -3而不是-2
-5的二进制:1111 1011 算术右移1位:1111 1101 = -3

而数学上-5 / 2 = -2.5,向零取整是-2

✅ 所以-5 >> 1 = -3,不等于-5 / 2 = -2






3. 对 2 的 n 次方取模

x % (2^n)

intmod_power_of_two(intx,intn){returnx&((1<<n)-1);}
  • 例子:10 % 4 = 210 & 3 = 2
  • 原理:2 的 n 次方减 1 的二进制是 n 个 1,与运算就相当于取后 n 位





4. 求整数的绝对值(不用 if 分支)

intabs(intx){intmask=x>>31;return(x^mask)-mask;}
  • 原理:
    • 正数的 mask 是 0,结果还是 x;
    • 负数的 mask 是 - 1(全 1),
      • (x ^ mask)取反:x ^ (-1)相当于按位取反
      • (x ^ mask) - mask;**加一:**减 - 1 相当于加 1,就是补码转原码






五、算法类技巧(面试高频)






1. 二进制中 1 的个数

用到了上面的‼️ 把最低位的 1置0

intcount_ones(intx){intcount=0;while(x){x&=x-1;// 每次清零最低位的1count++;}returncount;}
  • 时间复杂度:O (k),k 是 1 的个数,比循环 32 次快得多





2. 加法

intadd(inta,intb){while(b){intcarry=(unsignedint)(a&b)<<1;// 计算进位a^=b;// 无进位加法b=carry;}returna;}
  • 原理:

    • 异或^做无进位加法
    • &左移 1 位做进位
    • 循环直到进位为 0





3. 缺失的数字

所有出现两次的数都会抵消,剩下的就是缺失的数

intmissingNumber(vector<int>&nums){intres=nums.size();for(inti=0;i<nums.size();i++){res^=i^nums[i];}returnres;}





4. 只出现一次的数字系列

  • 一个数出现一次,其他出现两次:全部异或
  • 两个数出现一次,其他出现两次:先全部异或,再用最低位的 1 分组异或
  • 一个数出现一次,其他出现三次:统计每一位 1 的个数,模 3










七、重要注意事项(必看坑)

  1. 有符号数右移是算术右移:高位补符号位,负数右移结果和除法不同
  2. 左移溢出是未定义行为:不要左移超过类型的位数
  3. 1 << n是 int 类型:需要 64 位时用1LL << n
  4. x & (-x)对 INT_MIN 有效:但结果是 INT_MIN 本身,必须用 long long 避免溢出






面试必背速查表

常用技巧核心公式主要用途
判断奇数x & 1所有需要判断奇偶的地方
清零最低位的 1x & (x - 1)统计 1 的个数、判断 2 的幂
保留最低位的 1x & (-x)分组、树状数组
统计 1 的个数Brian Kernighan 算法位运算基础题
不用临时变量交换异或三次面试经典题
不用加减乘除加法异或 + 与左移面试高频题

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/2 20:07:41

在Linux上安装Kingbase 9

系统要求 https://help.kingbase.com.cn/v9/install-updata/install-linux/install-linux-2.html 环境准备 Linux版本:AlmaLinux release 9.4 (Seafoam Ocelot) Linux主机名:kbsrv informix安装包:KingbaseES_V009R001C001B0024_Lin64 informix服务名:kb01 内核参数…

作者头像 李华
网站建设 2026/6/2 20:07:19

基于C1815晶体管的立体声前置放大器DIY:从原理到实践

1. 项目概述与核心思路在折腾了不下十几种音频放大电路之后&#xff0c;我逐渐意识到&#xff0c;一个系统的“好声音”往往不是由最后的功率放大级决定的&#xff0c;前置放大和音调控制部分才是真正的灵魂。很多朋友在DIY功放时&#xff0c;会花大价钱购买发烧级的功放芯片或…

作者头像 李华
网站建设 2026/6/2 20:05:41

Arduino电容触控弹球游戏机:从传感器融合到交互设计实践

1. 项目概述与设计思路最近在工作室里捣鼓了一个特别有意思的小玩意儿&#xff0c;一个用Arduino和电容触控技术做的“开关弹球”游戏机。这可不是普通的弹球&#xff0c;它最大的亮点在于&#xff0c;整个游戏盘的边框内侧贴了一圈电容触控带&#xff0c;当那个小钢珠滚过边缘…

作者头像 李华
网站建设 2026/6/2 20:04:13

StreamCap:如何用一款工具实现40+直播平台的全自动录制?

StreamCap&#xff1a;如何用一款工具实现40直播平台的全自动录制&#xff1f; 【免费下载链接】StreamCap Multi-Platform Live Stream Automatic Recording Tool | 多平台直播流自动录制客户端 基于FFmpeg 支持监控/定时/转码 项目地址: https://gitcode.com/gh_mirrors/…

作者头像 李华
网站建设 2026/6/2 20:04:08

边缘计算中数据漂移的监测与应对:从原理到工程实践

1. 项目概述&#xff1a;边缘计算中的模型“漂移”危机在边缘计算场景下部署机器学习模型&#xff0c;听起来像是把智能直接送到了数据产生的源头&#xff0c;效率高、延迟低&#xff0c;听起来很美。但真正干过这事的工程师都知道&#xff0c;这里头藏着一个“沉默的杀手”——…

作者头像 李华
网站建设 2026/6/2 20:03:27

MySQL连接池原理与简易网站数据流动是如何进行的

mysql在我们定位(网站)1.mysql 连接池正常mysql connector是短链接&#xff0c;有点浪费所以mysql除了缓存方面的技术比如redis&#xff0c;在编码方面的技术叫做连接池原先是连接一下之后断开这时候我们可以建立一个连接池的小组件&#xff0c;预先地让多个线程预先跟mysql建立…

作者头像 李华