1、位运算符
程序中的所有数据在计算机内存中都是以二进制的形式储存的。
位运算就是直接对整数在内存中的二进制位进行操作
C语言提供了6个位操作运算符, 这些运算符只能用于整型操作数
(1)按位与:
只有对应的两个二进位均为1时,结果位才为1,否则为0
规律: 二进制中,与1相&就保持原位,与0相&就为0
9&5 = 1
1001
&0101
------
0001
(2)按位或:
只要对应的二个二进位有一个为1时,结果位就为1,否则为0
9|5 = 13
1001
|0101
------
1101
(3)按位异或
当对应的二进位相异(不相同)时,结果为1,否则为0
规律:
相同整数相的结果是0。比如55=0
多个整数相^的结果跟顺序无关。例如: 567=576
同一个数异或另外一个数两次, 结果还是那个数。例如: 577 = 5
9^5 = 12
1001
^0101
------
1100
(4)按位取反
各二进位进行取反(0变1,1变0)
~9 =-10
0000 0000 0000 0000 0000 1001 // 取反前
1111 1111 1111 1111 1111 0110 // 取反后
// 根据负数补码得出结果
1111 1111 1111 1111 1111 0110 // 补码
1111 1111 1111 1111 1111 0101 // 反码
1000 0000 0000 0000 0000 1010 // 源码 == -10
2、位运算应用场景
(1)判断奇偶(按位或)
偶数: 的二进制是以0结尾
8 -> 1000
10 -> 1010
奇数: 的二进制是以1结尾
9 -> 1001
11 -> 1011
任何数和1进行&操作,得到这个数的最低位
1000
&0001
-----
0000 // 结果为0, 代表是偶数
1011
&0001
-----
0001 // 结果为1, 代表是奇数
(2)权限系统
enum Unix {
S_IRUSR = 256,// 100000000 用户可读
S_IWUSR = 128,// 10000000 用户可写
S_IXUSR = 64,// 1000000 用户可执行
S_IRGRP = 32,// 100000 组可读
S_IWGRP = 16,// 10000 组可写
S_IXGRP = 8,// 1000 组可执行
S_IROTH = 4,// 100 其它可读
S_IWOTH = 2,// 10 其它可写
S_IXOTH = 1 // 1 其它可执行
};
// 假设设置用户权限为可读可写
printf("%d\n", S_IRUSR | S_IWUSR); // 384 // 110000000
(3)交换两个数的值(按位异或)
a = a^b;
b = b^a;
a = a^b;
(4)按位左移
把整数a的各二进位全部左移n位,高位丢弃,低位补0
由于左移是丢弃最高位,0补最低位,所以符号位也会被丢弃,左移出来的结果值可能会改变正负性
规律: 左移n位其实就是乘以2的n次方
2<<1; //相当于 2 *= 2 // 4
0010
<<0100
2<<2; //相当于 2 *= 2^2; // 8
0010
<<1000
(5)按位右移
把整数a的各二进位全部右移n位,保持符号位不变
为正数时, 符号位为0,最高位补0
为负数时,符号位为1,最高位是补0或是补1(取决于编译系统的规定)
规律: 快速计算一个数除以2的n次方
2>>1; //相当于 2 /= 2 // 1
0010
>>0001
4>>2; //相当于 4 /= 2^2 // 1
0100
>>0001
3、练习:
(1)写一个函数把一个10进制数按照二进制格式输出
#include <stdio.h>
void printBinary(int num);
int main(int argc, const char * argv[]) {
printBinary(13);
}
void printBinary(int num){
int len = sizeof(int)*8;
int temp;
for (int i=0; i<len; i++) {
temp = num; //每次都在原数的基础上进行移位运算
temp = temp>>(31-i); //每次移动的位数
int t = temp&1; //取出最后一位
if(i!=0&&i%4==0)printf(" "); printf("%d",t);
}
}
评论