移位操作符 与 位操作符

目录

1.移位操作符

1.1左移操作符 <<

1.2右移操作符 >>

 1.3注意事项

2.位操作符 &、|、^、~

2.1 &

2.1.1  &的定义

2.1.2 &的规则

2.2  |

2.2.1  |的定义

2.2.2 |的规则

2.3  ^

2.3.1  ^的定义

2.3.2  ^的规则

2.4  ~

2.4.1  ~的定义

2.3.2  ~的规则

3.运用

3.1.交换两个不同得数

3.2求⼀个整数存储在内存中的⼆进制中1的个数

3.2.1方法一

 3.2.2方法二

3.2.3方法三

3.3二进制位置置为0或1


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进行移位再取反操作,然后再与要变的数进行&操作

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值