理解位运算符

与运算符 &

两位同时为“1”,结果才为“1”,否则为“0”

1
2
1101 & 0010 = 0000;
1111 & 1101 = 1101;

或运算符 |

只要有一位为1,其值为1,否则位0

1
1000 | 1110 = 1110;

非运算符 ~

如果位为0,结果是1。如果位为1,结果是0

1
2
~1101 = 10
~00000001 = 11111110;

请注意计算机中负数编码的情况,在上篇博客中介绍过计算机是如何存负数的,所以在进行非运算转成十进制的时候,会出现不是你所想的结果,因为有可能是负数

异或运算符 ^

不同则为1,相同则为0 ,当且仅当两个运算值中有一个为1但不同时为1时,返回值为1

1
10010011 ^ 00111101 = 10101110

用法

设置位

1
2
3
flag = 0001
mask = 0010
flag = flag | mask = 0011

把flag的第二位设置为1,其他位不变

清空位

1
2
3
4
5
6
flag = 1111
mask = 0010
~mask = 1101
flag = flag & ~mask = 1111 & 1101 = 1101
//也可以写成
flag &= ~mask

mask中为 1 的位,在对应的flag的位置上会被清空位 0 ,其他位不会改变

切换位

也就是异或运算符

1
2
3
flag = 1111
mask = 0010
flag ^ mask = 1101

flag与mask中为 1 的位相对应的位都被切换为 0 ,mask为 0 的位则不改变

检查位

检查某个位的值为 1 还是 0 ,flag不能为 0

1
2
3
if((flag & mask) == mask){

}

flag & mask是为了覆盖flag中的其他位(叫掩码)
比如要检查第二个是否为 1

1
2
3
4
5
6
7
8
9
10
11
flag = 1101
mask = 0010
flag & mask = 0000
0000 != mask
//得出 flag的第二位是为 0

flag = 1111
mask = 0010
flag & mask = 0010
0010 == mask
//得出 flag的第二位是为 1

Andorid源码中的应用

保存多个状态

用到前面讲的设置位

android:layout_gravity="bottom|right"

这样,gravity的值就可以保存bottomright 两个状态,但是要注意这两个状态的值必须是不一致的

判断是否设置某状态

用到前面讲的检查位

1
2
3
4
5
6
int right = 0x001;
int bottom = 0x002;
int top = 0x008;
int state = right | bottom | top;
System.out.println("是否存在 right = " + ((state & right) == right));
System.out.println("是否存在 top = " + ((state & top) == top));

删除某个位的值

用到前面讲的清空位

1
2
3
4
5
6
7
8
int right = 0x001;
int bottom = 0x002;
int top = 0x008;
int state = right | bottom;
//删除right
state &= ~right;
//删除top
state &= ~top;

移位运算符

左移

二进制向左移动两位

1
2
3
4
10001010 << 2 = 00101000
//如果想让结果改变
int a = 1;
a <<= 2;

右移

二进制向右移动两位

对于无符号,直接丢弃右侧末端的值,空出的位用 0 填充

1
10001010 >> 2 = 00100010

对于有符号,取决于编译器

1
2
3
4
//一些编译器上获得这样的结果
10001010 >> 2 = 00100010
//另一些编译器上获得这样的结果
10001010 >> 2 = 11100010

用法

针对2次幂的值提供快速的乘法和除法

number << n = number乘以 2 的 n次幂
number >> n = number除以 2 的 n次幂

假设有一个long型表示颜色值,第一个字节存红色,第二个字节存绿色,第三个字节存蓝色,那么就可以取出不同颜色放入一个数组中

1
2
3
4
5
6
7
#define MASK 0XFF

long colors = 0x02a123d
char red,green,blue;
red = colors & MASK;
green = (colors >> 8) & MASK;
blue = (colors >> 16) & MASK;

red属于低字节,因此在内存中他们的位置是:

blue
green
red

&是对colors进行掩码操作,把其他位进行一个覆盖