当前位置: 首页 > news >正文

位操作:底层编程利器

目录

一、位操作符概述

二、基本位操作符

1、按位与(&)

2、按位或(|)

3、按位异或(^)

核心特性

1. 交换律

2. 结合律

3. 自反性(同一性)

4. 与0的关系

5. 可逆性

4、按位取反(~)

5、左移(<<)

6、右移(>>)

三、基本位操作示例

四、位操作应用:不借助临时变量交换两个整数

五、练习1:计算整数二进制表示中1的个数

方法1:除2取余法(有缺陷)

方法2:移位检测法

方法3:Brian Kernighan算法(最优)(超重要!!!)

六、练习2:二进制位操作 - 置位与清零

位操作技巧总结:

七、位操作符的应用

1、设置特定位

2、清除特定位

3、切换特定位

4、检查特定位

5、交换两个变量的值(不使用临时变量)

6、计算奇偶性

八、注意事项


一、位操作符概述

        位操作符是C语言中用于对数据的二进制位进行操作的运算符。它们直接操作整数类型的位模式,在底层编程、硬件操作和性能优化中非常有用。

        位操作符和逻辑运算符几乎一样的作用,只不过不同点是:位操作符是针对具体某一位的操作,而逻辑运算符是针对某一个具体逻辑的操作。可以类推......

C语言提供了以下几种位操作符,它们只能用于整数类型

  1. & - 按位与 (AND)

  2. | - 按位或 (OR)

  3. ^ - 按位异或 (XOR)

  4. ~ - 按位取反 (NOT)


二、基本位操作符

1、按位与(&)

  • 功能:对两个操作数的每一位执行逻辑与操作

  • 规则:只有两个对应位都为1时,结果位才为1

  • 示例:

    unsigned int a = 5;    // 0101
    unsigned int b = 3;    // 0011
    unsigned int c = a & b; // 0001 (1)

2、按位或(|)

  • 功能:对两个操作数的每一位执行逻辑或操作

  • 规则:只要有一个对应位为1,结果位就为1

  • 示例:

    unsigned int a = 5;    // 0101
    unsigned int b = 3;    // 0011
    unsigned int c = a | b; // 0111 (7)

3、按位异或(^)

  • 功能:对两个操作数的每一位执行异或操作

  • 规则:对应位不同时结果为1,相同时为0

  • 示例:

    unsigned int a = 5;    // 0101
    unsigned int b = 3;    // 0011
    unsigned int c = a ^ b; // 0110 (6)

核心特性

1. 交换律
a ^ b == b ^ a
2. 结合律
(a ^ b) ^ c == a ^ (b ^ c)
3. 自反性(同一性)
a ^ a == 0

任何数与自身异或结果为0

4. 与0的关系
a ^ 0 == a

任何数与0异或结果为其本身

5. 可逆性
a ^ b ^ b == a

异或同一个数两次会得到原数

4、按位取反(~)

  • 功能:对操作数的每一位执行取反操作

  • 规则:1变0,0变1

  • 示例:

    unsigned int a = 5;    // 0101
    unsigned int b = ~a;   // 1010 (取决于int的位数,假设4位时为10)

5、左移(<<)

  • 功能:将操作数的所有位向左移动指定的位数

  • 规则:右边空出的位用0填充,左边溢出的位被丢弃

  • 示例:

    unsigned int a = 5;    // 0101
    unsigned int b = a << 2; // 010100 (20)

6、右移(>>)

  • 功能:将操作数的所有位向右移动指定的位数

  • 规则:对于无符号数,左边空出的位用0填充;对于有符号数,取决于实现(通常用符号位填充)

  • 示例:

    unsigned int a = 20;   // 010100
    unsigned int b = a >> 2; // 000101 (5)

三、基本位操作示例

#include <stdio.h>int main()
{int num1 = -3;int num2 = 5;printf("%d\n", num1 & num2);  // 按位与printf("%d\n", num1 | num2);  // 按位或printf("%d\n", num1 ^ num2);  // 按位异或printf("%d\n", ~0);          // 按位取反return 0;
}


四、位操作应用:不借助临时变量交换两个整数

#include <stdio.h>int main()
{int a = 10;int b = 20;a = a ^ b;b = a ^ b;a = a ^ b;printf("a = %d b = %d\n", a, b);return 0;
}


五、练习1:计算整数二进制表示中1的个数

方法1:除2取余法(有缺陷)

#include <stdio.h>int main()
{int num = 10;int count = 0;while(num){if(num % 2 == 1)count++;num = num / 2;}printf("二进制中1的个数 = %d\n", count);return 0;
}

缺陷:对于负数会出错,因为负数的除法行为与预期不同。

方法2:移位检测法

#include <stdio.h>int main()
{int num = -1;int count = 0;for(int i = 0; i < 32; i++){if(num & (1 << i))count++;}printf("二进制中1的个数 = %d\n", count);return 0;
}

特点:需要循环32次,适用于所有整数,但效率不高。

方法3:Brian Kernighan算法(最优)(超重要!!!)

#include <stdio.h>int main()
{int num = -1;int count = 0;while(num){count++;num = num & (num - 1);  // 清除最右边的1}printf("二进制中1的个数 = %d\n", count);return 0;
}

优点:循环次数等于1的个数,效率最高。


六、练习2:二进制位操作 - 置位与清零

将数字13的第5位(从0开始计数)修改为1,然后再改回0:

#include <stdio.h>int main()
{int a = 13;// 13的二进制: 00000000000000000000000000001101// 将第5位置为1a = a | (1 << 4);  // 1左移4位到第5位printf("a = %d\n", a);  // 输出29 (000...00011101)// 将第5位清零a = a & ~(1 << 4);printf("a = %d\n", a);  // 输出13 (000...00001101)return 0;
}

位操作技巧总结

  • 将某位置1:num | (1 << n)

  • 将某位清零:num & ~(1 << n)

  • 切换某位状态:num ^ (1 << n)

  • 检查某位是否为1:num & (1 << n)

这些位操作在底层编程、嵌入式系统和性能优化中非常有用。


七、位操作符的应用

1、设置特定位

// 设置第n位(从0开始计数)
num |= (1 << n);

2、清除特定位

// 清除第n位
num &= ~(1 << n);

3、切换特定位

// 切换第n位的状态
num ^= (1 << n);

4、检查特定位

// 检查第n位是否设置
if (num & (1 << n)) {// 位已设置
}

5、交换两个变量的值(不使用临时变量)

a ^= b;
b ^= a;
a ^= b;

6、计算奇偶性

int is_odd = num & 1;  // 如果为1则是奇数,0则是偶数

八、注意事项

  1. 移位操作的位数:不能超过或等于操作数的位数,否则行为未定义

  2. 有符号数的右移:结果依赖于实现(算术移位或逻辑移位)

  3. 位操作符的优先级:通常低于算术运算符,建议使用括号明确优先级

  4. 可移植性:某些位操作假设特定的整数表示(如补码),可能影响可移植性

        位操作是C语言强大功能之一,合理使用可以显著提高程序效率和减少内存使用,但也需要谨慎以避免难以发现的错误。

http://www.lryc.cn/news/620960.html

相关文章:

  • 通过网页调用身份证阅读器http websocket方法-华视电子————仙盟创梦IDE
  • Uniapp 中 uni.request 的二次封装
  • 22.Linux samba服务
  • 15、C语言预处理知识点总结
  • 18.14 全量微调实战手册:7大核心配置提升工业级模型训练效率
  • 并发编程原理与实战(二十三)StampedLock应用实战与其他锁性能对比分析
  • 深度学习ubuntu系统常用指令和技巧
  • VisDrone数据集,专为无人机视觉任务打造
  • Linux面试题及详细答案 120道(1-15)-- 基础概念
  • 9.【C++进阶】继承
  • 开源数据发现平台:Amundsen 快速上手指南
  • 微服务、分布式概念-以及集群部署 vs 分布式部署
  • C# LINQ 全面教程:从入门到精通
  • 【19-模型训练细节 】
  • Linux 编译过程中遇到 TMPDIR 空间不足的问题
  • 算法应用上新!自适应更新策略差分进化算法求解球形多飞行器路径规划问题,附完整MATLAB代码
  • 智慧城市SaaS平台/专项管理系统
  • PyCharm 2025.2:面向工程师的 AI 工具
  • Nginx学习笔记(九)—— Nginx Rewrite深度解析
  • 学习嵌入式第二十八天
  • python爬虫学习(2)
  • 大模型微调方法讲解
  • linux 软硬链接详解
  • 服务器数据恢复—误删服务器卷数据的数据恢复案例
  • ESXI 6.7服务器时间错乱问题
  • QT+Yolov8 推理部署,ONNX模型 ,实例分割+目标检测
  • 【会员专享数据】2000-2024年我国乡镇的逐日PM₁₀数据(Shp/Excel格式)
  • 6、C 语言指针初阶知识点总结
  • AI搜索优化专家孟庆涛:以技术温度重构“人机信息对话”新范式
  • 前端Vite介绍(现代化前端构建工具,由尤雨溪开发,旨在显著提升开发体验和构建效率)ES模块(ESM)、与传统Webpack对比、Rollup打包