目录
1.移位操作符
移位操作符的操作数只能是整数
整数在计算机中采用的是补码形式进行存储
所以移位操作符操作的是补码
1.1左移操作符 <<
(1)规则:左边抛弃,右边补0
正数-------------------------------------------------------------------------------
负数 ----------------------------------------------------------------------------------------------
1.2右移操作符 >>
算术右移:右边丢弃,左边的符号位用原值的符号位填充
逻辑右移:有点丢弃,左边用0填充
具体实现依靠具体编译器进行实现
1.3注意事项
对于移位操作符,不要移动 负数位,这个标准是未定义的
a >> -1 //error
a << 1 //right
2.位操作符 &、|、^、~
这些 位操作符的操作数只针对整数
2.1 &
2.1.1 &的定义
&, 叫作 按位与
位,指的是整数在内存中以补码形式存储时的二进制位
2.1.2 &的规则
只有两个相应的位都为1时,结果的该位才为1,否则为0。
口诀:有0为0,无0为1
2.2 |
2.2.1 |的定义
|, 叫作 按位或
位,指的是整数在内存中以补码形式存储时的二进制位
2.2.2 |的规则
只要两个相应的位中有一个为1,结果的该位就为1。
口诀:有1为1,无1为0
2.3 ^
2.3.1 ^的定义
^, 叫作 按位异或
位,指的是整数在内存中以补码形式存储时的二进制位
2.3.2 ^的规则
只有两个相应的位不同(一个为0,一个为1)时,结果的该位才为1。
口诀:相同为0,相异为1
2.4 ~
2.4.1 ~的定义
~, 叫作 按位取反
位,指的是整数在内存中以补码形式存储时的二进制位
2.3.2 ~的规则
对一个整数的每一位执行逻辑取反操作。
口诀:0变为1,1变为0。
3.运用
3.1.交换两个不同得数
注意到:
1^3^1 = 3
1^1^3 = 3
异或是支持交换律的!
//创建第三个变量用于交换两个数
void swap1(int* a, int* b)
{
int c = *a;
*a = *b;
*b = c;
}
//利用两数之间的关系
void swap2(int* a, int* b)
{
//先求和
*a = *a + *b;
//用和减去b的值剩下a
*b = *a - *b;
//用和减去a的值剩下b
*a = *a - *b;
}
//用异或
void swap3(int* a, int* b)
{
*a = (*a) ^ (*b);
*b = (*a) ^ (*b);//*b = (*a) ^ (*b) ^ (*b) = *a;
*a = (*a) ^ (*b);//*b = (*a) ^ (*b) ^ (*a) = *b;
}
方法一需要创建第三个变量,通俗易懂
方法二不用创建第三个变量,但当a b非常大时有溢出的可能
方法三不用创建第三个变量,但是可读性不高
3.2求⼀个整数存储在内存中的⼆进制中1的个数
3.2.1方法一
就像十进制123通过模10除以10取得每一位数字一样
123%10=3
123/10 = 12
12%10 = 2
12/10 = 1
1%10 = 1
1/10 = 0 结束
十进制的7转化为二进制位00000111
也可以通过模2除以2得到相应的数字
7%2=1
7/2=3
3%2=1
3/2=1
1%2=1
1/2=0 结束
代码实现:
int NumberOf1( int n)
{
int count = 0;
while (n)
{
if (n % 2 == 1)
count++;
n = n / 2;
}
return count;
}
为什么传值传参为-1的时候 ,结果是0呢?
11111111111111111111111111111111
为-1的补码
结果应该是32 才对呀!
原因:代码中 n = n / 2 中 -1 / 2 = 0;函数结束,读取不到补码中的1
解决办法:将负数在传值传参时进行强制转换, 即
将有符号整数 int 转换成无符号整数 unsigned int
此时-1将被转换为一个极其大的整数,函数就可以读取补码中的1了
int NumberOf1(unsigned int n)
{
int count = 0;
while(n)
{
if(n%2==1)
count++;
n = n/2;
}
return count;
}
负数都能实现,整数就不用说了!
3.2.2方法二
通过右移操作符读取一个int型数据的每一个二进制位,
并与1进行&操作
如果结果为1就进行计数操作,
否则往后执行,直到进行完32次操作
代码实现
int NumberOf1(int n)
{
int count = 0;
int i = 0;
for(i=0; i<32; i++)
{
if(((n>>i)&1) == 1)
count++;
}
return count;
}
3.2.3方法三
n = n & (n-1)
二进制中:
1011&1010= 1010
1010&1001= 1000
1000&0111= 0000
注意到:
n & (n-1)会将n的二进制位中最后边的1变为0
所以反复进行n = n & (n-1),直到n为0为止!
int NumberOf1(int n)
{
int count = 0;
while(n)
{
n = n&(n-1);
count++;
}
return count;
}
3.3二进制位置置为0或1
编写代码将十进制的11的第8修改为1,然后再改回0
int a = 11;
//000000000000000000000000000001011
// 1
只需要将11的第8位与1进行按位或操作
再变回来时,需要对1进行移位再取反操作,然后再与要变的数进行&操作