4.5.4 一次求反运算符
一次求反运算符是一元运算符,它的作用仅是对运算数的位“翻转”。将运算数的每个是1的位翻转为0,而将每个是0的位翻转为1。此处提供真值表只是为了保持内容的完整性。
b1~b1
0 1
1 0
如果w1是short int,16位长,等于十六进制值a52f,那么对该值执行一次求反运算会得到十六进制值5ab0:
w1 1010 0101 0010 1111 0xa52f
~w1 0101 1010 1101 0000 0x5ad0
如果不知道运算中数值的准确位大小,那么一次求反运算符非常有用,使用它可让程序不会依赖于整数数据类型的特定大小。例如,要将类型为int的w1的最低位设为0,可将一个所有位都是1、但最右边的位是0的int值与w1进行与运算。所以像下面这样的C语句在用32位表示整数的机器上可正常工作。
w1&=0xFFFFFFFE;
如果用
w1&=~1;
替换上面的语句,那么在任何机器上w1都会同正确的值进行与运算。
这是因为这条语句会对1求反,然后在左侧会加入足够的1,以满足int的大小要求(在32位机器上,会在左侧的31个位上加入1)。
现在,显示一个实际的程序例子,说明各种位运算符的用途(参见代码清单4-7)。
代码清单4-7
//Bitwise operators illustrated
import<Foundation/Foundation.h>
int main(int argc, char*argv[])
{
NSAutoreleasePool*pool=[[NSAutoreleasePool alloc]init];
unsigned int w1=0xA0A0A0A0,w2=0xFFFF0000,
w3=0x00007777;
NSLog(@“x%x%x”,w1&w2,w1|w2,w1^w2);
NSLog(@“x%x%x”,~w1,~w2,~w3);
NSLog(@“x%x%x”,w1^w1,w1&~w2,w1|w2|w3);
NSLog(@“x%x”,w1|w2&w3,w1|w2&~w3);
NSLog(@“x%x”,~(~w1&~w2),~(~w1|~w2));
[pool drain];
return 0;
}
代码清单4-7输出
a0a00000 ffffa0a0 5f5fa0a0
5f5f5f5f ffff ffff8888
0 a0a0 fffff7f7
a0a0a0a0 ffffa0a0
ffffa0a0 a0a00000
对代码清单4-7中的每个运算都演算一遍,确定你理解了这些结果是如何得到的。
在第四个NSLog调用中,需要注意重要的一点,即按位与运算符的优先级要高于按位或运算符,因为这会实际影响表达式的最终结果值。有关运算符优先级的内容,请参考附录B。
第五个NSLog调用展示了DeMorgan的规则:~(~a&~b)等于a|b,~(~a|~b)等于a&b。