目录
位运算符
按位与'&'、按位或'|'、按位异或'^'、按位取反'~'
描述:
整数在计算机中用二进制的位来表示,C语言提供一些运算符可以直接操作整数中的位,称为位运算,这些运算符的操作数都必须是整型的。
按位与'&'
按位与运算符‘&’是指:参加运算的两个数据,按二进制位进行“与”运算。如果两个相应的二进制位都为1,则该位的结果值为1;否则为0。这里的1可以理解为逻辑中的true,0可以理解为逻辑中的false。
0 0 1 1 operand1 0 1 0 1 operand2 ---------- 0 0 0 1 (operand1 & operand2) - returned result
Arduino的int类型是一个16位的值,所以使用按位与‘&’运算时会同时对两个int的16位进行操作。
程序片段:
int a = 92; // in binary: 0000000001011100 int b = 101; // in binary: 0000000001100101 int c = a & b; // result: 0000000001000100, or 68 in decimal
按位或'|'
按位或运算符'|'是指:两个相应的二进制位中只要有一个为1,该位的结果值为1。借用逻辑学中或运算的话来说就是,一真为真。
0 0 1 1 operand1 0 1 0 1 operand2 ---------- 0 1 1 1 (operand1 | operand2) - returned result
程序片段:
int a = 92; // in binary: 0000000001011100 int b = 101; // in binary: 0000000001100101 int c = a | b; // result: 0000000001111101, or 125 in decimal.
示例程序:
对于程序员来说按位与'&'和按位或'|'常见工作是对一个端口进行读 – 写 – 修改。PORTD是个内置的常量,它设置数字引脚0,1,2,3,4,5,6,7的输出状态。如果其中一个位置为1,则该位置的引脚为HIGH。(该引脚需要用命令pinMode ()来设置输出),所以,如果我们写PORTD=B00110001,可以读取到引脚0,4,5的状态为HIGH。
int i; // 变量计数器 int j; void setup(){ DDRD = DDRD | B11111100; // 设置引脚2-7,留下0和1不变 (xx | 00 == xx) // 功能与用 pinMode(pin, OUTPUT) 设置引脚 2 - 7一样 Serial.begin(9600); } void loop(){ for (i=0; i<64; i++){ PORTD = PORTD & B00000011; // 清除引脚2-7状态,留下0和1不变 (xx & 11 == xx) j = (i << 2); // 通过左移运算改变引脚2-7状态,留下0和1不变 PORTD = PORTD | j; // 通过‘|’或运算更改LED的状态 Serial.println(PORTD, BIN); // 调试显示屏蔽 delay(100); } }
按位异或'^'
按位异或运算符'^'是指:参与运算的两数各对应的二进位相异或,当两对应的二进位相异时,结果为1
0 0 1 1 operand1 0 1 0 1 operand2 ---------- 0 1 1 0 (operand1 ^ operand2) - returned result
简单示例:
int x = 12; // binary: 1100 int y = 10; // binary: 1010 int z = x ^ y; // binary: 0110, or decimal 6
示例程序:
按位异或运算符‘^’通常用于翻转表达式里的一些位数(即1变0,0变1)。
// Blink_Pin_5 // demo for Exclusive OR void setup(){ DDRD = DDRD | B00100000; // 设置数字引脚5为输出 Serial.begin(9600); } void loop(){ PORTD = PORTD ^ B00100000; // 使其5位翻转 (引脚 5),其他不变 delay(100); }
按位取反'~'
按位取反运算符'~'是用于求整数的二进制反码,即分别将操作数各二进制位上的1变为0,0变为1。
0 1 operand1 ---------- 1 0 ~ operand1
int a = 103; // binary: 0000000001100111 int b = ~a; // binary: 1111111110011000 = -104
左移运算符'<<'、右移运算符'>>'
描述:
移位运算符(Bitwise Shift)包括左移'«'和右移'»'。左移将一个整数的各二进制位全部左移若干位。
左移运算符'<<'
最高两位的11被移出去了,最低两位又补了两个0,其它位依次左移两位。但要注意,移动的位数必须小于左操作数的总位数,比如上面的例子,左边是unsigned int型,如果左移的位数大于等于32位,则结果是Undefined。移位运算符不同于'+ - * / =='等运算符,两边操作数的类型不要求一致,但两边操作数都要做Integer Promotion,整个表达式的类型和左操作数提升后的类型相同。
右移运算符'>>'
最低两位的11被移出去了,最高两位又补了两个0,其它位依次右移两位。和左移类似,移动的位数也必须小于左操作数的总位数,否则结果是Undefined。在一定的取值范围内,将一个整数右移1位相当于除以2,小数部分截掉。
当操作数是有符号数时,右移运算的规则比较复杂:
☛如果是正数,那么高位移入0
☛如果是负数,那么高位移入1还是0不一定,这是Implementation-defined的。对于x86平台的gcc编译器,最高位移入1,也就是仍保持负数的符号位,这种处理方式对负数仍然保持了“右移1位相当于除以2”的性质。
综上所述,由于类型转换和移位等问题,用有符号数做位运算是很不方便的,所以,建议只对无符号数做位运算,以减少出错的可能。