4.1.2 按位运算符
&和 | 运算符还有一个作用:对数值执行操作。以这种方式使用时,它们处理的是变量中存储的一系列位,而不是变量值,因此它们称为按位运算符。
下面先讨论&和 |。&运算符第一个操作数中的每个位都与第二个操作数中相同位置上的位进行比较,在得到的结果中,各个位置上的位如表4-5所示。
| 运算符与此类似,但得到的结果位是不同的。如表4-6所示。
^运算符的用法与此相同。如果操作数中相同位置上的位有且仅有一个是1,其结果位就是1,如表4-7所示。
C#中还可以使用一元位运算符~,它将操作数中的位取反,其结果应是操作数中位为1的,在结果中就是0,反之亦然,如表4-8所示。
整数存储在.NET中的万式称为2的补位,即使用一元运算符~会使结果看起来有点古怪。假定int类型是一个32位的数字,则运算符~对所有32位进行操作,将有助于看出这种方式。例如,数字5的完整二进制表示为:
000000000000000000000000000000101
数字-5的完整二进制表示为:
111111111111111111111111111111011
实际上,按照2的补位系统,(-x)定义为(~x+1)。这个系统在把数字加在一起时非常有用。例如,把10和-5加起来(即从10中减去5)的二进制表示为:
000000000000000000000000000001010
+ 111111111111111111111111111111011
= 1000000000000000000000000000000101
note: 忽略最左端的1,就得到5的二进制表示。像~1=2这样的式子比较古怪,其原因是底层的结构强制生成了这个结果。
除了这4个按位运算符外,本节还要介绍另外两个运算符,如表4-10所示。
这些运算符通常称为位移运算符,最好用一个简单的示例加以说明:
int var1, var2 = 10, var3 = 2;
var1 = var2 << var3;
结果,varl的值是40。具体过程如下:10的二进制值是1010,把该数值向左移动两位,得到101000,即十进制中的40。 实际上,是执行了乘法操作。每向左移动一位,该数都要乘以2,所以向左移动两位,就给原来的操作数乘以4(2 * 2)。而每向右移动一位,则是给操作数除以2,并丢弃非整余数:
int var1, var2 = 10;
var1 = var2 >> 1;
在这个示例中,var1的值是5,而下面的代码得到的值是2:
int var1, var2 = 10;
var1 = var2 >> 2;
在大多数代码中,都不使用这些运算符,但应知道有这样的运算符存在。它们主要用于高度优化的代码,在这些代码中,不使用其他数学操作。因此它们通常用于设备驱动程序或系统代码。
位移运算符也有赋值运算符,如表4-11所示。