Objective-C中的位运算符用法

Objective-C语言中有各种各样的运算符可处理数字中的特定位,如下表所示:

符号运算

& 按位与
| 按位或
^ 按位异或
~ 一次求反
<< 向左移位
>> 向右移位

表中列出的所有运算符,除一次求反运算符(~)外,都是二元运算符,因此需要两个运算数。位运算符可处理任何类型的整型值,但不能处理浮点值。

1、按位运算符

对两个值执行与运算时,会逐位比较两个值的二进制表示。第一个值与第二个值对应位都为1时,在结果的对应位上就会得到1,其他的组合在结果中都得到0。如果b1和b2表示两个运算数的对应位,那么下表(称为真值表)就显示了在b1和b2所有可能值下对b1和b2执行与操作的结果。

b1 b2 b1 & b2
——————————
0 0 0
0 1 0
1 0 0
1 1 1

例如,如果w1和w2都定义为short int , w1等于十六进制的15 , w2等于十六进制的0c,那么以下C语句会将值0x04指派给w3。

w3 = w1 & w2;

将w1、w2和w3都表示为二进制后可更清楚地看到此过程,假设所处理的short int大小为16位。

w1 0000 0000 0001 0101 0x15
w2 0000 0000 0000 1100 & 0x0c
————————————————————
w3 0000 0000 0000 0100 0x04

按位与运算经常用于屏蔽运算。就是说,这个运算符可轻易地将数据项的特定位设置为0。例如,语句

w3 = w1 & 3;

将w1与常量3按位与所得的值指派给w3。它的作用是将w3中的全部位(而非最右边的两位)设置为0,并保留w1中最左边的两位。

与Objective-C中使用的所有二元运算符相同,通过添加等号,二元位运算符可同样用作赋值运算符。因此语句

word &= 15;

与下列语句

word = word & 15;

执行相同的功能。

此外,它还能将word的全部位设置为0,但最右边的四位除外。

2、按位或运算符

在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;

我们在后面会提供一个程序例子,演示如何使用按位或运算符。

3、按位异或运算符

按位异或运算符,通常称为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、一次求反运算

一次求反运算符是一元运算符,它的作用仅是对运算数的位“翻转”。将运算数的每个是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,可将一个所有位都是1、但最右边的位是0的int值与w1进行与运算。所以像下面这样的C语句在用32位表示整数的机器上可正常工作。

w1 &= 0xFFFFFFFE;

如果用

w1 &= ~1;

替换上面的语句,那么在任何机器上w1都会同正确的值进行与运算。

这是因为这条语句会对1求反,然后在左侧会加入足够的1,以满足int的大小要求(在32位机器上,会在左侧的31个位上加入1)。

现在,显示一个实际的程序例子,说明各种位运算符的用途

// Bitwise operators illustrated
#import
intmain (intargc,char*argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
unsignedintw1 = 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];
return0;
}

结果输出:

a0a00000 ffffa0a0 5f5fa0a0
5f5f5f5f ffff ffff8888
0 a0a0 fffff7f7
a0a0a0a0 ffffa0a0
ffffa0a0 a0a00000

对代码中的每个运算都演算一遍,确定你理解了这些结果是如何得到的。

在第四个NSLog调用中,需要注意重要的一点,即按位与运算符的优先级要高于按位或运算符,因为这会实际影响表达式的最终结果值。

第五个NSLog调用展示了DeMorgan的规则:(a & ~b)等于a | b,(a | ~b)等于a & b。

2、向左移位运算符

对值执行向左移位运算时,按照字面的意思,值中包含的位将向左移动。与该操作关联的是该值要移动的位置(或位)数目。超出数据项的高位的位将丢失,而从低位移入的值总为0。因此,如果w1等于3,那么表达式

w1 = w1 << 1;

可同样表示成

w1 <<= 1;

结果就是3向左移一位,这样产生的6将赋值给w1。

w1 ... 0000 0011 0x03

w1 << 1 ... 0000 0110 0x06

3、向右移位运算符

顾名思义,向右移位运算符(>>)把值的位向右移动。从值的低位移出的位将丢失。把无符号的值向右移位总是左侧(就是高位)移人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位或更多位时,并不会在计算机上产生规定的结果。还注意到,如果使用负数对值移位时,结果将同样是未定义的。

本文转自:http://www.cnblogs.com/pengyingh/articles/2357033.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,390评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,821评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,632评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,170评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,033评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,098评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,511评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,204评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,479评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,572评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,341评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,893评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,171评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,486评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,676评论 2 335

推荐阅读更多精彩内容