位运算符的使用

这篇文章我们一起来看看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)。

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


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

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

}</foundation>

结果输出:

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位或更多位时,并不会在计算机上产生规定的结果。还注意到,如果使用负数对值移位时,结果将同样是未定义的。

好了,通过这两篇文章的介绍,大家应该对Objective-C位运算符有一定了解了吧。

时间: 2024-10-10 08:59:09

位运算符的使用的相关文章

Java位运算符

位运算符 在Java中所有的数据都是以二进制数据的形式进行运算的,即如果是一个int型变量,要采用位运算时则必须将其变为二进制数据:每一 位二进制进行与.或.异或操作的结果如下: package com.test; public class Test { public static void main(String[] args) { int x = 3; int y = 6; System.out.println(x & y); System.out.println(x | y); Syste

Java的算数运算符、关系运算符、逻辑运算符、位运算符

Java的运算符,分为四类:                           算数运算符.关系运算符.逻辑运算符.位运算符.                           算数运算符:+  -  *  /  %  ++  --                           关系运算符:==  !=  >  >=  <  <=                           逻辑运算符:&&  ||  !  ^  &  |        

java注释 命名 数据类型 基本类型转换 位运算符 逻辑运算符 三目运算符

一.java注释 1.单行注释  //注释内容 2.多行注释 /*注释内容*/ 3.文档注释(可用javadoc工具生成api文档,不过我还没试过)/**文档注释*/,文档注释可以在使用的时候看见注释. 文档注释常用的标记 @auther作者 @version版本 @deprecated 不推荐使用 @param 本放的参数 @return 返回值 @throws异常,同@exception 二.java的命名 1.项目名 字母全部小写 2.包名 全部小写 3.类名 首字母大写加驼峰 4.方法名

Java的位运算符详解实例

Java的位运算符详解实例——与(&).非(~).或(|).异或(^).右移(>>).左移(<<).无符号右移(>>>) 位运算符主要针对二进制, 它包括了:“与”.“非”.“或”.“异或”."右移"."左移"."无符号右移". 从表面上看似乎有点像逻辑运算符, 但逻辑运算符是针对两个关系运算符来进行逻辑运算, 而位运算符主要针对两个二进制数的位进行逻辑运算. 下面详细介绍每个位运算符. 1.与运

Java的位运算符笔记

Java的位运算符有:&与.|或.^异或.~非.<<算术左移.>>算术右移.>>>逻辑右移 1. &(与) 全是1-->1 全是0-->0 有1有0-->0 例:000 111 010 101 000 111 101 101 ---------------------------- 000 111 000 101 1 int i = 1; //00000000000000000000000000000001 2 int j = 2

黑马程序员---C基础6【#include指令】【模块化编程】【计算机的进制】【原码、反码、补码】【位运算符】

------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- [#include指令] 1.文件包含命令的格式: 1)#include “”双引号是包含用户自己书写定义的文件(可以是头文件,也可以是普通的文件)#include是预处理指令,不是一个语句,不需要加封号 2)#include<>   包含一个系统(编译器自带)的头文件 2.文件包含的实质: 把指定文件内容插入该命令行位置取代该命令行, include不一定非要写在第一行: 3.includ

Java功底篇系列-03-一些位运算符你会如何理解?

话题一:异或 先看一段代码吧: 这段代码是用来实现a,b交换的. 异或是位运算符,0^1为1,其他情况都是0,这是一个加法不进位的功能! 这有什么用呢? 其实通过上面交换的例子,我们已经明白A^B^A将得到B,也就是可以实现数据还原的功能! 话题二:%与& 如果有一堆数据,我们想将这些数据通过HASH的方式,放入到桶中. 我们可以将桶进行编号,比如0号,1号,...N号桶. 给我们一个数据,我们要完成这个数据和桶的序号的映射转化关系,这样放入和查找就可以了. 由于对于任何一个非负数A,进行A%B

C语言的各种位运算符的操作简述

运算符: 算术运算符: + , - , * , / , % , ++ , -- 符合运算符: += , *= , /= , %= 条件运算符:  ? : 关系运算符: == , >= , <= , != , > , < 逻辑运算符: && , || , ! 赋值运算符: = 其他运算符: * , & , -> , . 位运算符: 1 > 按位与 &同时为一则为一 否则为零 3 & 5结果为 1(先将两个数化为二进制在进行计算) 3

类型转换、运算符、位运算符【以及原码、反码、补码】

1.类型转换 php中的‘+’与js有区别,php中+只是算术运算符[更偏向转化为数字].js更偏向转化为字符串 php本身的自动转换类型便符合大多数对类型的处理.[也有强制转换的情形出现] [注意转换关系:字符串转换成数字类型,开头的那部分字符串能够转化为数字(还要判断浮点型和整型)] 2.转换成布尔型[实现流程控制的关键] 以下值为false: (1)布尔值为false (2)整型值为0 (3)浮点型为0.0 (4)空字符串[字符串'0'(相当于是字符串做数组时是一个空字符串),区别,注意‘

&#39;&lt;&lt;&#39; &#39;|&#39; &#39;&gt;&gt;&#39; 等位运算符 课本祥解

a<<1   相当于a*2     a>>1    相当于a/2   a<<|1   相当于a*2+1 一些算法用得到. '<<' '|' '>>' 等位运算符 课本祥解