(9)位运算

1. 位运算的概念

位运算操作的是整数在内存中的二进制位。C 语言提供了以下几种位运算操作符:

按位与(&)
  • 运算规则:将两个操作数对应的二进制位进行与运算。只有当两个对应位都为 1 时,结果位才为 1,否则为 0。
  • 示例代码
#include <stdio.h>int main() {int num1 = 5;  // 二进制表示为 0101int num2 = 3;  // 二进制表示为 0011int result = num1 & num2;  // 0101 & 0011 = 0001printf("5 & 3 的结果: %d\n", result);return 0;
}
按位或(|)
  • 运算规则:将两个操作数对应的二进制位进行或运算。只要两个对应位中有一个为 1,结果位就为 1。
  • 示例代码
#include <stdio.h>int main() {int num1 = 5;  // 二进制表示为 0101int num2 = 3;  // 二进制表示为 0011int result = num1 | num2;  // 0101 | 0011 = 0111printf("5 | 3 的结果: %d\n", result);return 0;
}
按位异或(^)
  • 运算规则:将两个操作数对应的二进制位进行异或运算。当两个对应位不同时,结果位为 1;相同时,结果位为 0。
  • 示例代码
#include <stdio.h>int main() {int num1 = 5;  // 二进制表示为 0101int num2 = 3;  // 二进制表示为 0011int result = num1 ^ num2;  // 0101 ^ 0011 = 0110printf("5 ^ 3 的结果: %d\n", result);return 0;
}
取反(~)
  • 运算规则:对操作数的每一位进行取反操作,0 变为 1,1 变为 0。需要注意的是,取反操作符是单目运算符,它对一个操作数进行操作。
  • 示例代码
#include <stdio.h>int main() {int num = 5;  // 二进制表示为 00000101int result = ~num;  // 取反后为 11111010(在有符号整数表示中,这是 -6 的补码形式)printf("~5 的结果: %d\n", result);return 0;
}
左移(<<)
  • 运算规则:将操作数的所有二进制位向左移动指定的位数,右边空出的位用 0 填充。左移一位相当于乘以 2。
  • 示例代码
#include <stdio.h>int main() {int num = 5;  // 二进制表示为 00000101int result = num << 2;  // 左移 2 位后为 00010100,即 20printf("5 << 2 的结果: %d\n", result);return 0;
}
右移(>>)
  • 运算规则:将操作数的所有二进制位向右移动指定的位数。对于无符号数,左边空出的位用 0 填充;对于有符号数,如果是算术右移(大多数编译器的实现方式),左边空出的位用符号位填充。右移一位相当于除以 2(对于无符号数和正数)。
  • 示例代码
#include <stdio.h>int main() {int num = 12;  // 二进制表示为 00001100int result = num >> 2;  // 右移 2 位后为 00000011,即 3printf("12 >> 2 的结果: %d\n", result);return 0;
}

2. 位段的概念

位段(bit - field)是一种特殊的结构体成员,它允许以位为单位指定结构体成员所占的存储空间大小。通过位段,可以更紧凑地存储数据,尤其是在处理一些硬件相关的数据或者需要节省内存空间的情况下。

以下是位段的示例:

#include <stdio.h>// 定义一个包含位段的结构体
struct BitFieldExample {unsigned int field1 : 3;  // 位段 field1 占 3 位unsigned int field2 : 5;  // 位段 field2 占 5 位unsigned int field3 : 4;  // 位段 field3 占 4 位
};int main() {struct BitFieldExample example;example.field1 = 3;  // 二进制为 011,存储在低 3 位example.field2 = 7;  // 二进制为 00111,存储在接下来的 5 位example.field3 = 9;  // 二进制为 1001,存储在再接下来的 4 位// 注意:位段的存储顺序和字节顺序(大端序或小端序)有关,这里假设为小端序// 结构体总共占 2 个字节(3 + 5 + 4 = 12 位,向上取整到字节)unsigned short int *ptr = (unsigned short int *)&example;printf("存储的值(十六进制): 0x%x\n", *ptr);return 0;
}

在这个示例中,struct BitFieldExample结构体中的成员field1field2field3都是位段。它们在内存中是紧凑存储的,总共占用不超过一个整数的空间(这里假设为 2 个字节,因为总共 12 位)。

3. 在程序中应用位运算

设置和清除特定的位
  • 设置某一位为 1(使用按位或)
    假设要将一个整数num的第n位(从右往左数,最低位为第 0 位)设置为 1。可以使用以下代码:
#include <stdio.h>int main() {int num = 10;  // 二进制为 1010int n = 1;     // 设置第 1 位num = num | (1 << n);  // 将第 1 位设置为 1,结果为 1010 | 0010 = 1010printf("设置第 %d 位后的结果: %d\n", n, num);return 0;
}
  • 清除某一位为 0(使用按位与和取反)
    要将一个整数num的第n位清除为 0,可以使用以下代码:
#include <stdio.h>int main() {int num = 10;  // 二进制为 1010int n = 2;     // 清除第 2 位num = num & ~(1 << n);  // 将第 2 位清除为 0,结果为 1010 & 1011 = 1000printf("清除第 %d 位后的结果: %d\n", n, num);return 0;
}
检查特定的位是否为 1(使用按位与)
#include <stdio.h>int main() {int num = 10;  // 二进制为 1010int n = 1;     // 检查第 1 位if (num & (1 << n)) {printf("第 %d 位是 1\n", n);} else {printf("第 %d 位是 0\n", n);}return 0;
}
位运算在枚举中的应用(使用位掩码)

可以使用位运算来实现枚举类型中的多个标志位。例如:

#include <stdio.h>// 定义枚举类型,每个枚举值对应一个位掩码
enum Options {OPTION_A = 1 << 0,  // 0001OPTION_B = 1 << 1,  // 0010OPTION_C = 1 << 2   // 0100
};int main() {int options = OPTION_A | OPTION_C;  // 设置选项 A 和 C,二进制为 0101if (options & OPTION_A) {printf("选项 A 被选中\n");}if (options & OPTION_B) {printf("选项 B 被选中\n");}if (options & OPTION_C) {printf("选项 C 被选中\n");}return 0;
}

在这个示例中,通过位运算可以方便地组合和检查枚举类型中的多个选项。位运算在底层编程、硬件驱动开发、数据压缩、加密算法等领域都有广泛的应用。通过灵活运用位运算,可以提高程序的效率和优化内存使用。

希望以上内容能满足您的需求,如果您还有其他问题,请随时提问。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/58826.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Jmeter命令监控CPU等指标

JMeter 命令行执行脚本得到的报告中&#xff0c;是没有CPU、内存使用率等监控数据的&#xff0c;但是可以使用JMeter插件帮忙。 一、下载jmeter-plugins-manager.jar 下载后将文件放到jmeter安装包lib/ext目录下。打开Jmeter》菜单栏》选项》Plugins Manager 二、安装PerfMon…

江协科技STM32学习- P32 MPU6050

&#x1f680;write in front&#x1f680; &#x1f50e;大家好&#xff0c;我是黄桃罐头&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流 &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd;​…

原生html+js+css+php多图上传带预览可增删判断图片大小和后缀

原生htmljscssphp多图上传带预览可增删&#xff0c;前后端判断图片大小和后缀 源码来自AI&#xff0c;有改动&#xff0c;整合亲测可用 <?php // 设置允许的最大文件大小为 2MB $maxFileSize 2 * 1024 * 1024; $allowedExtensions [jpg, jpeg, png, gif];// 上传目录&am…

java设计模式之创建者模式(5种)

设计模式 软件设计模式&#xff0c;又称为设计模式&#xff0c;是一套被反复利用&#xff0c;代码设计经验的总结&#xff0c;他是在软件设计过程中的一些不断发生的问题&#xff0c;以及该问题的解决方案。 **创建者模式又分为以下五个模式&#xff1a;**用来描述怎么“将对象…

如何一键更换ppt模板?掌握这2个ppt技巧快速搞定!

每当要制作ppt&#xff0c;很多人会第一时间去搜刮各种ppt模板&#xff0c;有时我们找到了一份貌似符合需求的模板&#xff0c;等到了ppt制作环节&#xff0c;才发现离我们的预期相距甚远&#xff0c;做到一半的ppt如何换模板呢&#xff1f; 想要在中途更换ppt模板&#xff0c;…

操作系统笔记(五)信号量,经典的IPC问题(读写者问题...)

信号量 一个信号量是一个包含两部分内容的数据结构&#xff1a; (a) 一个整数计数器, COUNT (b) 一个记录阻塞进程ID的队列, Q 信号量有两个原子操作&#xff1a; UP(V操作&#xff09; 和 DOWN (P操作) DOWN(S): if (S.count > 0) S.count …

[UVM] objection笔记

1.raise_objection&drop_objection 成对出现 2.在进入到某一phase时&#xff0c;UVM会收集此phase提出的所有objection&#xff0c;并且实时监测所有objection是否已经被撤销了&#xff0c;当发现所有都已经撤销后&#xff0c;那么就会关闭此phase&#xff0c;开始进入下一…

臻于智境 安全护航 亚信安全受邀出席新华三智算新品发布会

近日&#xff0c;紫光股份旗下新华三集团在北京隆重举办了主题为“乘势 进化 臻于智境”的新华三智算新品发布会。作为新华三集团的长期战略合作伙伴&#xff0c;亚信安全受邀参会&#xff0c;亚信安全CEO马红军出席发布仪式&#xff0c;并与来自各界的业界伙伴共同探讨智能化…

【解决】Ubuntu18.04 卸载python之后桌面异常且终端无法打开,重启后进入tty1,没有图形化界面

我因为python版本太过于混乱 &#xff08;都是为了学习os&#xff09; &#xff0c;3.6—3.9版本我都安装了&#xff0c;指向关系也很混乱&#xff0c;本着“重装是最不会乱”的原则&#xff0c;我把全部版本都卸载了。然后装了3.9 发现终端打不开了&#xff0c;火狐浏览器的图…

2-140 基于Solidworks和Matlab Simulink Simscape仿真的机器人手臂仿真

基于Solidworks和Matlab Simulink Simscape仿真的机器人手臂仿真&#xff0c;使用Simulink-Simscape Multibody模块&#xff0c;完成SW-Simscape-Multibody-Link-Plugin手臂仿真&#xff0c;通过调节关节实现手臂动作&#xff0c;并显示三坐标位置。程序已调通&#xff0c;可直…

流媒体协议.之(RTP,RTCP,RTSP,RTMP,HTTP)(一)

闲着没事做&#xff0c;记录一下开发项目用过的协议&#xff0c;项目中&#xff0c;大多是是实时显示播放的&#xff0c;通过私有协议&#xff0c;传输到上位机&#xff0c;实时播放&#xff0c;延时小于200ms&#xff0c;仿照这些协议&#xff0c;定义的数据格式。如果用这些协…

【数据结构 | C语言】单身狗进化

这一天晚上,弯通又做梦了,并且梦到了一个帅气的男孩纸!这个男孩给了弯通一个数字 n。男孩离开前告诉弯通,n!(n 的阶乘)的位数就是距离弯通脱单的天数。矜持的弯通想知道自己还有多久能脱单,快写个程序帮助他! 输入格式:输入第一行为一个正整数 n(1<=n<=25000)…

通过思维导图【脑图】梳理Java 开发技术栈

通过思维导图【脑图】梳理Java 开发技术栈 前言一、思维导图概述二、Java 开发技术栈1.整体脑图结构2.基础知识3.核心语法4.高级特性5.常用框架6.数据库7.算法8.设计模式9.最佳实践10.资源推荐 附思维导图原件总结我是将军我一直都在&#xff0c;。&#xff01; 前言 将军深刻…

Mac “屏幕保护程序启动或显示器关闭后需要密码“无效

屏幕保护程序启动或显示器关闭后需要密码只能选择“立即”的解决方法&#xff1a; 在 iPhone mirror中设置&#xff0c;每次询问权限。 参考&#xff1a;https://support.apple.com/en-us/120421

Oracle 大表添加索引的最佳方式

背景&#xff1a; 业务系统中现在经常存在上亿数据的大表&#xff0c;在这样的大表上新建索引&#xff0c;是一个较为耗时的操作&#xff0c;特别是在生产环境的系统中&#xff0c;添加不当&#xff0c;有可能造成业务表锁表&#xff0c;业务表长时间的停服势必会影响正常业务…

基于matlab的凸包(Convex Hull)算法理解与测试

基于matlab的凸包Convex Hull算法理解与测试 0 引言1 Graham扫描算法原理2 Graham扫描算法实现3 Graham扫描算法关键函数4 结语 0 引言 &#x1f4bb;&#x1f4bb;AI一下&#x1f4bb;&#x1f4bb; 凸包算法是计算给定点集的最小凸包的一种算法。凸包是包含给定点集中所有点…

golang有序map

最近使用go开发排行榜的需求, 有些情况会用到有序map, 但是go竟然没有有序map的实现 本着自己动手丰衣足食的原则, 就自己实现了一个 原理 原理比较简单, 主要结合了container/list双向链表和map 使用双向链表存储key和value, 保证顺序, 使用map存储key和节点信息, 保证查找…

Conmi的正确答案——在Kibana中搜索Elasticsearch的索引

Elasticsearch版本&#xff1a;7.17.25 Kibana版本&#xff1a;7.17.25 0、进入首页 1、点击空间名“默”&#xff08;我的默认空间名就是“默认”&#xff09;&#xff1b; 2、点击气泡弹窗的“管理空间”进入管理页面&#xff1b; 3、点击“索引模式”&#xff0c;进入索引模…

Elasticsearch Date类型,时间存储相关说明

本文介绍了在SpringBoot中处理Elasticsearch中日期时间格式的问题。当时间输出为UTC格式并存在时区差异时&#xff0c;可通过设置字段格式如yyyy-MM-dd HH:mm:ss并指定时区为GMT8来解决。存储Date类型数据时&#xff0c;可以使用JSON库如json-lib, fastjson, Jackson或gson进行…

QT访问数据库:应用提示Driver not loaded

在QT中运行完全正确错误截图 解决办法1 我用的是MySQL。我把libmysql.dll复制到应用程序的目录下&#xff0c;即可正常访问数据库。 解决办法2 bool open_work_db() {QString info "support drivers:";for (int i0; i<QSqlDatabase::drivers().size(); i){inf…