C程序设计 01-位运算及位段
一、位运算
1.定义
位运算是按二进制位进行的运算。
2.位运算符

3.异或运算及其应用
①相等为0,不等为1;
②交换两个值:a=a^b; b=b^a; a=a^b;
4.说明
①位运算的运算对象只能是int或char类型的数据;
②注意位运算符的运算顺序:~ <<(>>) & ^ |
二、位运算的应用:数字范围按位与
题目描述
给定范围[m, n],其中0 <= m <= n <= 2147483647,返回此范围内所有数字的按位与(包含 m, n 两端点)。
样例输入
5 7
样例输出
4
解题思路及代码
若迭代计算范围内每个数字,会造成较大的耗时,因此需要寻找一组连续数字按位与的规律。
经过观察可以发现,对所有数字执行按位与运算的结果与所有的二进制数有着相同的前缀,而运算结果的该前缀后面的二进制位全为0。因此问题转化为求范围内二进制数的公共前缀。
方法一:位移。将两个数字不断向右移动,直到数字相等,即数字被缩减为它们的公共前缀。
方法二:Brian Kernighan算法。每次对number和number-1之间进行按位与运算后,number中最右边的1会被抹去变成0。
int main() { //Brian Kernighan算法
int m, n;
scanf("%d %d", &m, &n);
while(m < n) {
n &= (n - 1);
}
printf("%d\n", n);
}
详细题解及动画演示见力扣官方题解。
三、位段
1.位段类型及位段
位段类型是一种特殊的结构类型,其所有成员均以二进制位为单位定义长度,并称成员为位段,或称位域。
2.定义及引用
struct packed_data {
unsigned a : 2;
unsigned b : 6;
unsigned c : 4;
unsigned d : 4;
}data;
data.a = 2; //对位段中的数据进行引用
data.b = 25;
data.c = 15;
3.说明
①位段成员的类型必须是unsigned或int类型;
②位段赋值时要注意取值范围;
③一个位段必须存储在同一个存储单元,不能跨两个存储单元。如果某个存储单元空间不能容纳下一个位段,则从下一个单元起存放该位段;
④可以定义无名位段,表示相应空间不用,或定义长度为0的无名位段,表示下一个位段从下一存储单元开始存放。
struct packed_data {
unsigned a : 2;
unsigned b : 4;
unsigned : 0;
unsigned c : 3;
unsigned : 3;
unsigned d : 2;
}data;
四、参考资料
1.数字范围按位与_力扣官方题解:https://leetcode-cn.com/problems/bitwise-and-of-numbers-range/solution/shu-zi-fan-wei-an-wei-yu-by-leetcode-solution/
2.位运算_百度百科:https://baike.baidu.com/item/位运算/6888804?fr=aladdin

浙公网安备 33010602011771号