按位运算
C语言有这些按位运算的运算符
- & 按位的与
- | 按位的或
- ~ 按位取反
- ^ 按位的异或
- << 左移
- >> 右移
按位与&
- 如果x的第i位是1且y的第i位是1,那么(x&y)的第i位是1,否则的话(x&y)的第i位是0
- 按位与常用于两种应用:
- 让某一位或某些位为0
- 取一个数中的一段
按位或|
- 如果x的第i位是1或y的第i位是1,那么(x|y)的第i位是1,否则的话(x|y)的第i位是0
- 按位或常用于两种应用:
- 让某一位或某些位为1
- 把两个数拼起来
按位取反~
- 把1位变0,0位变1
- 想要得到全部位为1的数:~0
逻辑运算VS按位运算
- 对于逻辑运算,它只看到两个值:0和1
- 可以认为逻辑运算相当于把所有非0值都变成1,然后做按位运算
按位异或
- 如果x的第i位和y的第i位相等,那么(x^y)的第i位是0,否则的话(x^y)的第i位是1
- 如果两个位相等,那么结果为0;不相等,结果为1
- 对一个变量用同一个值异或两次,等于什么也没做
曾经面试金山WPS的时候有一道题问到:不使用额外的空间,交换两个整形数字。
有两种方法
方法一:算术方法
x = x + y; y = x - y; x = x - y;
方法二:异或方法
x = x^y;// 只能对int,char.. y = x^y; x = x^y;
移位运算:左移<<
- i << j
- i中所有的位向左移动j个位置,而右边填入0
- 所有小于int的类型,移位以int的方式来做,结果是int
- x = x<<1 等价于 x = x*2
- x = x<<n 在范围内等价于x = x*(2的n次方)
移位运算:右移>>
- i >> j
- i中所有的位向右移j位
- 所有小于int的类型,移位以int的方式来做,结果是int
- 对于unsigned的类型,左边填入0
- 对于signed的类型,左边填入原来的最高位
- x = x>>1 等价于 x = x/2
- x = x>>n 等价于 x = x/(2的n次方)
no zuo no die
- 移位的位数不要用负数,这是没有定义的行为
利用按位与和移位操作实现输出一个数的二进制:
#include<stdio.h> int main(int argc,int *argv[]) { int number; scanf("%d",&number); unsigned int mask = 1; mask = mask << 31; while(mask) { if(number & mask) { printf("1"); } else { printf("0"); } mask = mask>>1; } return 0; }
位段
把一个int的若干位组合成一个结构
如:
struct U0 { unsigned int leading : 3; unsigned int FLAG1:1; unsigned int FLAG2:1; int trailing :27; };
- 这样就可以直接用位段的成员名称来访问,以移位、与、或更方便
- 编译器会安排其中的位的排列,不具有可移植性
- 当所需的位超过一个int时会采用多个int