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。