关于位运算的笔记

前言

2017年11月19日
关于学习位操作,我可能会阐述个人理解以及在实际生活和在编程中的使用,将位操作和生活和编程更好的联系起来,以帮助自己理解,使学习更加深入,所以可能会有一些误解和错误的方面,希望可以和本人交流指出错误之处,感激不尽。


二进制

1.0b表示二进制数,但是C中不可用。
2.一个字节中有8位(bit),无符号可以表示0~255之间的数字(unsigned char);有符号可表示-128~+127(signed char);

二进制浮点型

1.使用幂作为分母例如 2^(-1);
2.二进制只能精确表示多个1/2的幂之和;

按位运算

逻辑运算符

按位运算逻辑运算符:~(取反)、&(按位与)、|(按位或),^(按位异或);

取反

取反~:每一位上0变1,1变0;

a ~a
0 1
1 0

~11001100 = 00110011

按位与

按位与&:每一位上其中一个为0则取0,都为1则取1;

a b a&b
0 0 0
0 1 0
1 0 0
1 1 1

10010011 & 00111101 = 0010001

按位或

按位或|:每一位上其中一个为1则取1,都为0则取0;

a b a或b
0 0 0
0 1 1
1 0 1
1 1 1

10010011 | 00111101 = 10111111

按位异或

按位异或^:每一位上两个相同则为0,不同则为1;

a b a^b
0 0 0
0 1 1
1 0 1
1 1 0

10010011^00111101 = 10101110

异或特性

异或偶数次会变回原来的数字

移位运算符

左移: <<

左移运算符将原有的数字向左移动指定的位数;移出左末端的位数将会丢失,而右端则会用‘0’补充空缺的位置。
(10001010) << 2 = (00101000) //可以看出,数字向左移动两位,左末端数字丢失,右端补‘0’
这样的操作产生了新的数字,但是并不会赋值,例如

1
2
int num = 1;
num << 2;

这种操作中,num依旧是1,并不会有任何改变;若需要改变变量,则需要 <<= 来实现;

1
2
int num = 1;
num <<= 2; //等价于 num = num << 2;

右移: >>

与左移基本相同;在右移运算中,右末端位数将会丢失;但是,对于左末端而言。对于无符号类型,将会用‘0’补齐空位;而对于有符号类型,结果将取决于机器,空出的符号可用‘0’补充,或者用符号位的副本补充。例如:

1
2
(10001010) >> 2
(00100010)

1
2
(10001010) >> 2
(11100010)

以上是有符号类型在不同机器上的不同运算结果,而下面是无符号类型的运算结果

1
2
(10001010) >> 2
(00100010)

右移运算符(>>=)与左移运算符用法基本相同;

移位运算符的用法

移位运算符针对2的幂提供快速有效的乘法和除法:

1
2
number << n; //number 乘于 2 的 n 次幂
number << n; //number 除于 2 的 n 次幂

这些运算相当于十进制中移动小数点来乘于10或除于10的操作。

代码实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//用移位制作流水灯项目
#include<reg52.h>
void delay(int t); //设置延时函数delay( ms)
int main(void){
unsigned int i = 0;
while(1){
for(i = 0;i <= 7; i++){
P1 = ~(0x01 << i); //利用取反和移位实现LED灯流水效果
delay(100);
}
for(i = 0;i <= 7; i++){
P1 = ~(0x80 >> i);
delay(100);
}
}
return 0;
}
void delay(int t){
int i;
while(t--)
for( i = 0;i < 70;i++);
}

参考书籍

《C Primer Plus》,《C和指针》,《C语言从入门到精通》,《编码(code):隐匿在计算机软硬件背后的语言》,《手把手教你学51单片机》