Arduino语法-位运算
语法列表
- & (位与)
- | (位或)
- ^ (位异或)
- ~ (位非)
- << (左移)
(右移)
位与说明
按位与(&)
按位操作符在变量的位级执行运算。它们帮助解决各种常见的编程问题。以下大部分资料来自一个有关位数学的优秀教程,或许可以在这里找到。[1]
描述和语法
以下是所有这些运算符的描述和语法。更详细的资料或许可以在参考指南中找到。
按位与(&)
在C++中按位与运算符是单个与符号,
用于其它两个整型表达式之间使用。按位与运算独立地在周围的表达式的每一位上执行操作。根据这一规则:如果两个输入位都是1,结果输出1,否则输出0。表达这一思想的另一个方法是:
0 0 1 1 operand1
0 1 0 1 operand2
----------
0 0 0 1 (operand1 & operand2) - returned result
在Arduino中,int型是16位的。所以在两个整型表达式之间使用&将会导致16个与运算同时发生。代码片断就像这样:
int a = 92; // in binary: 0000000001011100
int b = 101; // in binary: 0000000001100101
int c = a & b; // result: 0000000001000100, or 68 in decimal.
在a和b的16位的每一位将使用按位与处理。且所有16位结果存入C中,以二进制存入的结果值01000100,即十进制的68。
按位与的其中一个最常用的用途是从一个整型数中选择特定的位,常被称为掩码屏蔽。看如下示例:
位或说明
按位或(|)
在C++中按位或运算符是垂直的条杆符号,|。就像&运算符,|独立地计算它周围的两个整型表达式的每一位。(当然)它所做的是不同的(操作)。两个输入位其中一个或都是1按位或将得到1,否则为0。换句话说:
0 0 1 1 operand1
0 1 0 1 operand2
----------
0 1 1 1 (operand1 | operand2) - returned result
这是一个使用一小断C++代码描述的按位或(运算)的例子:
int a = 92; // in binary: 0000000001011100
int b = 101; // in binary: 0000000001100101
int c = a | b; // result: 0000000001111101, or 125 in decimal.
按位与和按位或的一个共同的工作是在端口上进行程序员称之为读-改-写的操作。在微控制器中,每个端口是一个8位数字,每一位表示一个引脚的状态。写一个端口可以同时控制所有的引脚。
PORTD是内建的参照数字口0,1,2,3,4,5,6,7的输出状态的常量。如果一个比特位是1,那么该引脚置高。(引脚总是需要用pinMode()指令设置为输出模式)。所以如果我们写入PORTD = B00110001;我们就会让引脚2,3和7输出高。一个小小的问题是,我们同时也改变了某些引脚的0,1状态。这用于Arduino与串口通讯,所以我们可能会干扰串口通讯。
我们的程序规则是:
仅仅获取和清除我们想控制的与相应引脚对应的位(使用按位与)。
合并要修改的PORTD值与所控制的引脚的新值(使用按位或)。
int i; // counter variable
int j;
void setup(){
DDRD = DDRD | B11111100; // set direction bits for pins 2 to 7, leave 0 and 1 untouched (xx | 00 == xx)
// same as pinMode(pin, OUTPUT) for pins 2 to 7
Serial.begin(9600);
}
void loop(){
for (i=0; i<64; i++){
PORTD = PORTD & B00000011; // clear out bits 2 - 7, leave pins 0 and 1 untouched (xx & 11 == xx)
j = (i << 2); // shift variable up to pins 2 - 7 - to avoid pins 0 and 1
PORTD = PORTD | j; // combine the port information with the new information for LED pins
Serial.println(PORTD, BIN); // debug to show masking
delay(100);
}
}
位异或说明
按位异或(^)
在C++中有一个有点不寻常的操作,它被称为按位异或,或者XOR(在英语中,通常读作“eks-or”)。按位异或运算符使用符号^。该运算符与按位或运算符“|”非常相似 ,唯一的不同是当输入位都为1时它返回0。
0 0 1 1 operand1
0 1 0 1 operand2
----------
0 1 1 0 (operand1 ^ operand2) - returned result
看待XOR的另一个视角是,当输入不同时结果为1,当输入相同时结果为0。
这里是一个简单的示例代码:
int x = 12; // binary: 1100
int y = 10; // binary: 1010
int z = x ^ y; // binary: 0110, or decimal 6
“^”运算符常用于翻转整数表达式的某些位(例如从0变为1,或从1变为0)。在一个按位异或操作中,如果相应的掩码位为1, 该位将翻转,如果为0,该位不变。以下是一个闪烁引脚5的程序.
// Blink_Pin_5
// demo for Exclusive OR
void setup(){
DDRD = DDRD | B00100000; // set digital pin five as OUTPUT
Serial.begin(9600);
}
void loop(){
PORTD = PORTD ^ B00100000; // invert bit 5 (digital pin 5), leave others untouched
delay(100);
}
位非说明
按位取反(~)
在C++中按位取反运算符为波浪符“~”。不像“&”和“|”,按位取反运算符应用于其右侧的单个操作数。按位取反操作会翻转其每一位。0变为1,1变为0。例如:
0 1 operand1
1 0 ~ operand1
int a = 103; // binary: 0000000001100111
int b = ~a; // binary: 1111111110011000 = -104
看到此操作的结果为一个负数:-104,你可能会感到惊讶,这是因为一个整型变量的最高位是所谓的符号位。如果最高位为1,该整数被解释为负数。这里正数和负数的编码被称为二进制补码。欲了解更多信息,请参阅维基百科条目:补码。
顺便说一句,值得注意的是,对于任何整数x, ~x 与 -x-1 相等。
有时候,符号位在有符号整数表达式中能引起一些不期的意外。
左移、右移说明
左移运算(<<),右移运算(>>)
描述
From The Bitmath Tutorial in The Playground
在C++中有两个移位运算符:左移运算符<<和右移运算符>>。这些运算符将使左边操作数的每一位左移或右移其右边指定的位数。
语法
variable << number_of_bits
variable >> number_of_bits
参数
*variable - (byte, int, long) number_of_bits integer <= 32
示例:
int a = 5; // binary: 0000000000000101
int b = a << 3; // binary: 0000000000101000, or 40 in decimal
int c = b >> 3; // binary: 0000000000000101, or back to 5 like we started with
当把x左移y位(x << y),x中最左边的y位将会丢失。
int a = 5; // binary: 0000000000000101
int b = a << 14; // binary: 0100000000000000 - 101中的第一个1被丢弃
如果您确信没有值被移出,理解左移位运算符一个简单的办法是,把它的左操作数乘2将提高其幂值。例如,要生成2的乘方,可以使用以下表达式:
1 << 0 == 1
1 << 1 == 2
1 << 2 == 4
1 << 3 == 8
...
1 << 8 == 256
1 << 9 == 512
1 << 10 == 1024
...
当把x右移y位,x的最高位为1,该行为依赖于x的确切的数据类型。如果x的类型是int,最高位为符号位,决定x是不是负数,正如我们在上面已经讨论过的。在这种情况下,符号位会复制到较低的位:
int x = -16; // binary: 1111111111110000
int y = x >> 3; // binary: 1111111111111110
该行为,被称为符号扩展,常常不是你所期待的。反而,你可能希望移入左边的是0。事实上右移规则对于无符合整型表达式是不同的。所以你可以使用强制类型转换来避免左边移入1。
int x = -16; // binary: 1111111111110000
int y = (unsigned int)x >> 3; // binary: 0001111111111110
如果你可以很小心地避免符号扩展,你可以使用右移位运算符>>,作为除以2的幂的一种方法。例如
int x = 1000;
int y = x >> 3; // 1000除以8,得y = 125.
获取最新文章: 扫一扫右上角的二维码加入“创客智造”公众号