0x01——位运算

本文介绍了二进制在编程中的基础知识,包括位运算的优先级、位与memset的使用、移位运算以及二进制状态压缩。讲解了如何利用位运算进行数组压缩存储,并举例说明了在解决实际问题如最短Hamilton路径和起床困难综合症中的应用。还探讨了位的其他特性,如成对变换和lowbit运算,这些在图论和数据结构中有着重要应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

基础知识及二进制常见用法

  • 前言

bit是度量信息的单位,包含0和1两种状态。计算机的各种运算最后无不归结位一个个bit的变化。熟练掌握并利用位运算,能够帮助我们理解程序运行中的种种表现,提高程序循行的时空效率,降低编程复杂度。

  • 运算符优先级

从左到右优先级依次降低

加减 移位 比较大小 位与 异或 位或
+,- <<,>> <,>==,!= & xor(C++^) |
  • 位与memset

我们都知道,memset可以以字节为单位初始化变量或者数组,这里有几个特>别的数字:

  • 0x3F3F3F3F 1061109567
    -> 0x7F7F7F7F 2147483647
  • 0xFFFFFFFF -1

观察这几个数字,我们会发现0x3F3F3F3F是个很有用的数字,原因如下:

  • 可以直接用memset初始化
  • 0x3F3F3F3F的两倍不会超过int的最大范围
  • 这个数足够大

这也是常常使用INF = 0x3F3F3F3F的原因

memset(a,0x3f,sizeof a);
  • 移位运算
>> <<
即除以2向下取整 1 < < n = 2 n , n < < 1 = 2 ∗ n 1<<n = 2^{n} , n<<1 = 2 * n 1<<n=2n,n<<1=2n

例题:

  1. a^b
  2. 64位整数乘法
  • 二进制状态压缩

二 进 制 状 态 压 缩 , 是 指 将 一 个 长 度 为 m 的 b o o l 数 组 用 一 个 m 位 的 二 进 制 整 数 表 示 {\color{Red} 二进制状态压缩,是指将一个长度为m的bool数组用一个m位的二进制整数表示} mboolm
并 储 存 的 方 法 。 利 用 下 列 位 运 算 操 作 可 以 实 现 原 b o o l 数 组 中 对 应 下 标 的 存 取 。 {\color{Red} 并储存的方法。利用下列位运算操作可以实现原bool数组中对应下标的存取。} bool

### C语言中的位运算及其应用 #### 什么是位运算位运算是指对二进制数的每一位进行操作的一种计算方式。它广泛应用于嵌入式开发、算法优化以及数据压缩等领域。通过直接操作二进制位,可以显著提高程序运行效率并减少内存占用。 #### 常见的位运算符 以下是C语言中常见的位运算符及其功能: 1. **按位与 (`&`)** 对两个操作数的对应位逐一比较,只有当两位都为 `1` 时结果才为 `1`,否则为 `0`。 2. **按位或 (`|`)** 对应位只要有一个为 `1`,结果就为 `1`;如果两者的对应位均为 `0`,则结果为 `0`。 3. **按位异或 (`^`)** 如果对应的两位不同,则结果为 `1`;相同则结果为 `0`。 4. **取反 (`~`)** 将操作数的每一位取反,即将所有的 `1` 转换为 `0`,所有的 `0` 转换为 `1`。 5. **左移 (`<<`)** 和 **右移 (`>>`)** 左移表示将操作数的所有位向左移动指定数量的位置,并在右侧补零。右移则是将所有位向右移动指定位置,在左侧补零(对于无符号整型)或者复制最高有效位(对于有符号整型)。 这些基本概念可以通过以下代码示例进一步说明[^1]: ```c #include <stdio.h> int main() { unsigned char a = 0b00110011; // 十六进制表示也可以写成 0x33 unsigned char b = 0b11001100; printf("a & b: %X\n", (unsigned int)(a & b)); // 输出 0xC printf("a | b: %X\n", (unsigned int)(a | b)); // 输出 0xFF printf("a ^ b: %X\n", (unsigned int)(a ^ b)); // 输出 0xF3 printf("~a : %X\n", (unsigned int)(~a)); // 输出 FFFFFFC printf("a << 2: %X\n", (unsigned int)(a << 2)); // 输出 CC printf("a >> 2: %X\n", (unsigned int)(a >> 2)); // 输出 0XC return 0; } ``` 上述代码展示了如何利用不同的位运算实现特定的功能。例如,通过按位与(`&`)来检测某些标志位的状态,而通过按位或(`|`)设置新的标志位状态等。 #### 解决实际问题的应用场景 - **提取字节的一部分**:假设需要获取某个变量低8位的数据,可以直接使用掩码配合按位与完成此任务。比如 `(data & 0xFF)` 可以得到最低的有效字节。 - **判断奇偶性**:由于任何整数的最后一位决定了其奇偶性质,因此可以用简单的表达式如 `(num & 1)` 来快速判定一个数值是否为奇数。 - **交换两个变量而不借助第三个临时存储空间**: ```c void swap(int *x, int *y){ if (*x != *y){ *x ^= *y; *y ^= *x; *x ^= *y; } } ``` 这段函数实现了不依赖额外辅助变量的情况下互换两个整型值的内容。 #### 关于结构体大小测量的问题解释 针对提问者提到的具体例子——即语句 `printf("%d", sizeof(struct date) + sizeof(max))` 的含义分析如下:这里涉及到了C标准库函数 `sizeof()` ,用于返回给定类型的对象所占有的字节数量。然而具体输出取决于定义好的 `struct date` 结构体成员布局情况以及编译器对该类型的实际分配策略(包括填充规则),还有max可能代表的是另一个已声明的对象或者是宏常量等等因素共同决定最终打印出来的数字是多少。 #### OpenCV 中 SGBM 参数调整的影响 虽然这部分内容主要讨论了计算机视觉领域里的立体匹配方法之一半全局块匹配(Semi Global Block Matching),但它同样涉及到一些底层参数调节背后蕴含的技术细节。例如其中一句关键配置命令 `setSpeckleRange(32)` 表明允许的最大视差跳跃幅度被设定成了32像素单位长度以内。这意味着一旦发现局部区域内存在超出这个范围的变化趋势就会被认为是非合理的结果从而强制置零处理掉相应部分的估计误差项[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值