位运算符
运算符 功能 用法
~ 按位非 ~expr
<< 左移 expr1 >> expr2
>> 右移 expr1 & expr2
& 按位与 expr1 & expr2
^ 按位异或 expr1 ^ expr2
| 按位或 expr1 | expr2
&= 按位与赋值 expr1 &= expr2
^= 按位异或赋值 expr1 ^= expr2
|= 按位或赋值 expr1 |= expr2
位运算符把操作数解释成有序的位集合,每个位的值是 0 或 1。位运算符允许程序员设置或测试独立的位
1. 按位非运算符~
该操作符的作用是翻转操作数的每一位。如果某位是 1,则改为 0;如果某位是 0,则改为 1。
例如:
short a = 5;
short b = ~a;
// b 的值是-6
短整型 5的二进制是 0000 0101,每位取反,则结果值的二进制是 1111 1010(补码 减一取反得到负数),即-6。 注意咯我们是在补码的基础上 来运算的。切记是补码 正负数都行;
2. 左移运算符<<和右移运算符>>
该操作符的作用是将其左边操作数的位向左或向右移动,移动的位数是右边的操作数。例如:
short a = 5 << 1;
short b = 5 >> 2;
//5 左移 1 位的二进制结果是 0000 1010,即十进制的 10
// 5 右移 2 位的二进制结果是 0000 0001,即十进制的 1
在移位过程中,某些位被移到存储区外面,则该位将被丢弃。左移运算符(<<)从右边开始
用 0 补空位。
左移同样是在补码的基础上进行运算的
对于右移运算符(>>),如果操作数是无符号数,则从左边开始插入 0;如果操作数
是有符号数,则插入符号位的复制值或者插入 0,这由具体的编译器决定。
因为右移涉及到了符号位的变化。。。所以就相对复杂的点点咯。
127的补码:0111 1111
右移二位: 0001 1111 -> 原码同补码一样 对应十进制:31
-128的补码:1000 0000
右移二位: 1110 0000 -> 这个补码对应的原码为:1010 0000 对应十进制:-32
3.对于进行按位与运算的两个整数操作数的每个位,如果两个操作数在该位处都是 1,则结果值
的该位为 1,否则为 0
4、对于进行按位异或运算的两个整数操作数的每个位,如果两个操作数在该位处只有一个是 1
(注意不是两个同时为 1),则结果值的该位为 1,否则为 0。
5、对于按位或运算的两个整数操作数的每个位,如果两个操作数在该位处只有一个是 1,则结果
值的该位为 1,如果都是 0,则结果值的该位为 0
注意了,这些所有的位运算符都是在补码的基础上进行的。。。 琢磨着是因为在计算机系统中,数值一律用补码来表示(存储)。
举一个比较有用的实例
不用临时变量交换两个整数
void exchange(int i , int j)
{
i = i^j;
j =j ^i;
i =i^ j;
}
两次异或就变回去了。。。。。这是个好东西呀 有意思
一晃4天又过了。。。。。
shmily_h