这篇文章咱们一块儿来看看Objective-C位运算符。Objective-C语言中有各类各样的运算符可处理数字中的特定位,以下表所示:html
符号 | 运算 |
& | 按位与 |
| | 按位或 |
^ | 按位异或 |
~ | 一次求反 |
<< | 向左移位 |
>> | 向右移位 |
表中列出的全部运算符,除一次求反运算符(~)外,都是二元运算符,所以须要两个运算数。位运算符可处理任何类型的整型值,但不能处理浮点值。spa
一、按位运算符code
对两个值执行与运算时,会逐位比较两个值的二进制表示。第一个值与第二个值对应位都为1时,在结果的对应位上就会获得1,其余的组合在结果中都获得0。若是b1和b2表示两个运算数的对应位,那么下表(称为真值表)就显示了在b1和b2全部可能值下对b1和b2执行与操做的结果。htm
b1 b2 b1 & b2
——————————
0 0 0
0 1 0
1 0 0
1 1 1blog
例如,若是w1和w2都定义为short int , w1等于十六进制的15 , w2等于十六进制的0c,那么如下C语句会将值0x04指派给w3。ci
w3 = w1 & w2;get
将w一、w2和w3都表示为二进制后可更清楚地看到此过程,假设所处理的short int大小为16位。it
w1 0000 0000 0001 0101 0x15
w2 0000 0000 0000 1100 & 0x0c
————————————————————
w3 0000 0000 0000 0100 0x04io
按位与运算常常用于屏蔽运算。就是说,这个运算符可轻易地将数据项的特定位设置为0。例如,语句table
w3 = w1 & 3;
将w1与常量3按位与所得的值指派给w3。它的做用是将w3中的所有位(而非最右边的两位)设置为0,并保留w1中最左边的两位。
与Objective-C中使用的全部二元运算符相同,经过添加等号,二元位运算符可一样用做赋值运算符。所以语句
word &= 15;
与下列语句
word = word & 15;
执行相同的功能。
此外,它还能将word的所有位设置为0,但最右边的四位除外。
二、按位或运算符
在Objective-C中对两个值执行按位或运算时,会逐位比较两个值的二进制表示。此时,只要第一个值或者第二个值的相应位是1。那么结果的对应位就是1。按位或操做符的真值表以下所示。
b1 b2 b1 | b2
———————————
0 0 0
0 1 1
1 0 1
1 1 1
因此,若是w1是short int,等于十六进制的19, w2也是short int,等于十六进制的6a,那么对w1和vv2执行按位或会获得十六进制的7b,以下所示:
w1 0000 0000 0001 1001 0x19
w2 0000 0000 0110 1010 | 0x6a
————————————————————
0000 0000 0111 1011 0x7b
按位或操做一般就称为按位OR,用于将某个词的特定位设为1。例如,如下语句将w1最右边的三位设为1,而无论这些位操做前的状态是什么都是如此。
w1 = w1 | 07;
固然,能够在语句中使用特殊的斌值运算符,以下面的语句所示:
w1 |= 07;
咱们在后面会提供一个程序例子,演示如何使用按位或运算符。
三、按位异或运算符
按位异或运算符,一般称为XOR运算符,遵照如下规则:对干两个运算数的相应位,若是任何一个位是1,但不是二者全为1,那么结果的对应位将是1,不然是0。该运算符的真值表如
下所示:
b1 b2 b1 ^ b2
————————————
0 0 0
0 1 1
1 0 1
1 1 0
若是w1和w2分别等于十六进制的5e和d6,那么w1与w2执行异或运算后的结果是十六进制值e8,以下所示:
w1 0000 0000 0101 1110 0x5e
w2 0000 0000 1011 0110 ^ 0xd6
——————————————————————
0000 0000 1110 1000 0xe8
本文就先讲到这里,对于Objective-C位运算符咱们下一篇继续探讨,下次主要讨论一下Objective-C位运算符中的一次求反、向左移位运算、向右移位运算,下回见。
一、一次求反运算
一次求反运算符是一元运算符,它的做用仅是对运算数的位“翻转”。将运算数的每一个是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 0x5ab0
若是不知道运算中数值的准确位大小,那么一次求反运算符很是有用,使用它可以让程序不会依赖于整数数据类型的特定大小。例如,要将类型为int的w1的最低位设为0,可将一个全部位都是一、但最右边的位是0的int值与w1进行与运算。因此像下面这样的C语句在用32位表示整数的机器上可正常工做。
w1 &= 0xFFFFFFFE;
若是用
w1 &= ~1;
替换上面的语句,那么在任何机器上w1都会同正确的值进行与运算。
这是由于这条语句会对1求反,而后在左侧会加入足够的1,以知足int的大小要求(在32位机器上,会在左侧的31个位上加入1)。
如今,显示一个实际的程序例子,说明各类位运算符的用途
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
结果输出:
a0a00000 ffffa0a0 5f5fa0a0
5f5f5f5f ffff ffff8888
0 a0a0 fffff7f7
a0a0a0a0 ffffa0a0
ffffa0a0 a0a00000
对代码中的每一个运算都演算一遍,肯定你理解了这些结果是如何获得的。
在第四个NSLog调用中,须要注意重要的一点,即按位与运算符的优先级要高于按位或运算符,由于这会实际影响表达式的最终结果值。
第五个NSLog调用展现了DeMorgan的规则:~(~a & ~b)等于a | b,~(~a | ~b)等于a & b。
二、向左移位运算符
对值执行向左移位运算时,按照字面的意思,值中包含的位将向左移动。与该操做关联的是该值要移动的位置(或位)数目。超出数据项的高位的位将丢失,而从低位移入的值总为0。所以,若是w1等于3,那么表达式
w1 = w1 << 1;
可一样表示成
w1 <<= 1;
结果就是3向左移一位,这样产生的6将赋值给w1。
w1 ... 0000 0011 0x03
w1 << 1 ... 0000 0110 0x06
三、向右移位运算符
顾名思义,向右移位运算符(>>)把值的位向右移动。从值的低位移出的位将丢失。把无符号的值向右移位老是左侧(就是高位)移人0。对于有符号值而言,左侧移入1仍是0依赖于被移动数字的符号,还取决于该操做在计算机上的实现方式。若是符号位是0(表示该值是正的),无论哪一种机器都将移人0。然而,若是符号位是1,那么在一些计算机上将移人1,而其余计算机上则移入0。前一类型的运算符一般称为算术右移,然后者一般称为逻辑右移。
若是w1是unsigned int,用32位表示它而且它等于+六进制的F777EE22,那么使用语句
w1 >>= 1;
将w1右移一位后,w1等于十六进制的7BBBF711,以下所示:
w1 1111 0111 0111 0111 1110 1110 0010 0010 0xF777EE22
w1 >> 1 0111 1011 1011 1011 1111 0111 0001 0001 0x7BBBF711
若是将w1声明为(有符号)的short int,在某些计算机上会获得相同的结果;而在其余计算机上,若是将该运算做为算术右移来执行,结果将会是FBBBF711。
应该注意到,若是试图用大于或等于该数据项的位数将值向左或向右移位,那么该Objective-C语言并不会产生规定的结果。所以,例如计算机用32位表示整数,那么把一个整数向左或向右移动32位或更多位时,并不会在计算机上产生规定的结果。还注意到,若是使用负数对值移位时,结果将一样是未定义的。
好了,经过这两篇文章的介绍,你们应该对Objective-C位运算符有必定了解了吧。