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

(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.mrgr.cn/news/63514.html

相关文章:

  • 力扣:120. 三角形最小路径和
  • TensorFlow 预训练目标检测模型集合
  • vue框架总览
  • 如何打开/关闭 GitLab 的版本检查功能?
  • 设计模式07-结构型模式(装饰模式/外观模式/代理模式/Java)
  • 12. MapReduce全局计数器
  • 用友U8采购入库单与旺店通·企业奇门集成方案解析
  • [CSP篇] CSP2024 游记(下)
  • 机器学习:我们能用机器学习来建立投资模型吗
  • C++模拟实现list
  • 第5章第6章 Servlet技术
  • 【果实种子识别】Python+深度学习+人工智能+CNN卷积神经网络算法+TensorFlow+算法模型训练
  • 【升华】机器学习鸢尾花分类完整代码示例
  • 助力抑郁症初筛!上海交大团队构建Agent心理诊所,论文一作在线展示demo,分享技术亮点
  • Games101笔记-三维Transform变换(三)
  • python--函数详解二
  • ngnix.conf文件配置前后端联调地址
  • 8.FreeRTOS之软件定时器
  • Linux云计算 |【第五阶段】CLOUD-DAY7
  • MYSQL插入或修改,基于唯一联合索引,批量操作
  • CentOS上安装Redis 6.x
  • 还在寻找影像切片方案?免费GIS工具箱满足你的需求
  • 外发出去的文件怎么加密?2024年6款外发文件加密软件app盘点,赶紧收藏!
  • AutoGLM:智谱AI的创新,让手机成为你的生活全能助手
  • Allegro: 开源的高级视频生成模型
  • Apache Dubbo (RPC框架)