左右位移、按位与、或、异或和取反符号的解析与使用实例

本文详细介绍了按位与(&), 按位或(|), 按位异或(^), 取反(~)以及左右位移操作在编程中的应用,包括交换数值、计数二进制1的个数和修改二进制位等实例。通过C语言代码演示了这些操作及其原理。
摘要由CSDN通过智能技术生成

目录

按位与 &

解析

按位或 |

 解析

按位异或 ^

解析

按位取反 ~

解析

 左右位移操作符     右 >>      左 <<

 操作符的使用实例

 按位异或 ^

 不创建第三个变量来交换两个数的值 

 按位与& 与 位移操作符>> 

编码实现: 求一个整数存储在内存中的二进制中1的个数(即求补码的二进制中1的个数)

按位或 | 异或 ^ 取反 ~ 的一个例子 将一个二进制数中任意位置的0改为1

结束语



按位与 &

​#include<stdo.h>
int main() {
	int a = 3;
	int b = -5;
	int c = a & b;

	printf("a & b =%d\n",c);   //结果为3
    return 0;
}

解析

a的二进制位:> 
00000000000000000000000000000011 原码
00000000000000000000000000000011 反码
00000000000000000000000000000011 补码

b的二进制位:> 
00000000000000000000000000000101 原码
11111111111111111111111111111010 反码
11111111111111111111111111111011 补码

//按位与的运算规则 : 有0取0,只有当都是1的时候才取1

00000000000000000000000000000011 补码  3  
11111111111111111111111111111011 补码 -5
00000000000000000000000000000011 补码  c
//注意正数的三码都是一样的
//打印的时候按原码打印,因此值会为 3
​

按位或 |

#include<stdio.h>
int main() {
	int a = 3;
	int b = -5;
	int d = a | b;
	
    printf("a | b =%d\n",d);
    return 0;                    //值会为 -5
}

 解析

	//按位或的运算规则 : 有1取1,只有当都是0的时候才取0

			 3 :>  00000000000000000000000000000011 补码
	        -5 :>  11111111111111111111111111111011 补码

	         d :>  11111111111111111111111111111011 补码 负数的要转化成原码再打印出来
			 d :>  11111111111111111111111111111010 反码 减去一个1
			 d :>  10000000000000000000000000000101 原码 首位是符号位不需要取反

按位异或 ^

#include<stdio.h>
int main() {
	int a = 3;
	int b = -5;
	int t = a ^ b;

    printf("a ^ b =%d\n",t);        //结果会为-8
	return 0;
}

解析

            //按位异或的运算规则 : 相同为0,相异为1

			 3 :>  00000000000000000000000000000011 补码
	        -5 :>  11111111111111111111111111111011 补码
	         t :>  11111111111111111111111111111000 补码
			 t :>  11111111111111111111111111110111 反码 
			 t :>  10000000000000000000000000001000 原码 

	        //打印的时候按原码打印,因此值会为 -8

按位取反 ~

#include<stdio.h>
int main() {
	int a = 0;  //0 可以当做整数
		
	printf(" a =%2d\n~a =%2d\n",a,~a);    //得-1

	//同样的
	int b = 3;
		
	printf(" b =%2d\n~b =%2d",b,~b);     //得-4

	return 0;
}

解析

a的二进制位    
00000000000000000000000000000000 原码
00000000000000000000000000000000 反码
00000000000000000000000000000000 补码
按位取反后
11111111111111111111111111111111 补码
11111111111111111111111111111110 反码
10000000000000000000000000000001 原码
//该值为-1

//同样的
b的二进制位     
00000000000000000000000000000011 原码
00000000000000000000000000000011 反码
00000000000000000000000000000011 补码


11111111111111111111111111111100 补码  按位取反
11111111111111111111111111111011 反码  按位取反
10000000000000000000000000000100 原码  按位取反
//该值为-4

 左右位移操作符     右 >>      左 <<

补上字符是用 

负数 在使用 位移左<< 的时候是不需要移动 符号位(首字符) 

#include<stdio.h>
int main() {
	int a = 2;					// a    :>	 00000000000000000000000000000010	原码
								//  	:>	 00000000000000000000000000000001   右位移
	int b = a >> 1;                                    //得1
	printf("  a =%d\n  a>>1 =%d\n",a,b);		

	//当时负数时
	int x = -2;
	int y = x << 1;				//x     :>   10000000000000000000000000000010   
								//      :>   10000000000000000000000000000100   左位移 
                                                        //得-4
	printf("  x =%d\n  x<<1 =%d\n", x, y);

	return 0;
}

注意:对于移位操作,不要移动随意移动负数位,这个是标准未定义的,即使在很多的编译器下是可以运行的

 操作符的使用实例

 按位异或^

 不创建第三个变量来交换两个数的值 

//方法一 但是这种方法可能会出现溢出的现象
int main() {
	int a = 3;
	int b = -5;
	
	printf("交换前:> a =%2d,b =%2d\n" ,a,b);

	a = a + b;
	b = a - b;
	a = a - b;

	printf("交换后:> a =%2d,b =%2d\n" ,a,b);

	return 0;
}

首先很容易想到是这么一种方法,把两数相加然后再分别减掉各数就可以拿到,但是这种方法会出现溢出的情况,所以我们使用或按位异的方法就可以很容易得到

//方法二 使用按位异或的操作运算符 
#include<stdio.h>
int main() {
	int a = 3;
	int b = -5;
		
	printf("交换前:> a =%2d,b =%2d\n" ,a,b);
	
	a = a ^ b; //3^-5
	b = a ^ b; //3^-5^-5   相同的两数异或为0 ,而任意的数异或 0 为本身
	a = a ^ b; //3^-5 ^3   这里的^3(是第2次运算后的b的值)
						//而且这种方法是支持加法交换率的 
						//比如:3^-5^-5 结果为3     而 -5 ^3^-5 结果还是为3
	
	printf("交换后:> a =%2d,b =%2d\n" ,a,b);

	return 0;
}

 按位与& 与 位移操作符>> 

编码实现: 求一个整数存储在内存中的二进制中1的个数(即求补码的二进制中1的个数)

//编码实现: 求一个整数存储在内存中的二进制中1的个数
//即求补码的二进制中1的个数

#include<stdio.h>
int binary(int n) {
	int count = 0;
	int  i = 0;
	for ( i = 0; i < 32; i++)
	{
		if ((n>>i) &1 ==1)		//注意是移动n的二进制位啊!
		{
			count++;
		}
	}
	return count;
}
int main() {
	int n = 0;
	scanf("%d" ,&n);

	int ret = binary(n);
	printf("n在内存中的二进制中1的个数:>%d\n",ret);
	return 0;
}

按位或 | 异或 ^ 取反 ~ 的一个例子 将一个二进制数中任意位置的0改为1

//按位或的一个例子
 
//将一个二进制数中任意位置的0改为1
#include<stdio.h>
int main() {
	int a = 13;
	int n = 0;
	scanf("%d", &n); //输入移动的位置,次数要减去一
	printf("改前 a =%d\n",a);


	//a 的二进制位  :>   00000000000000000000000000001101 原码
	//			   :>  00000000000000000000000000001101 反码
	//             :>  00000000000000000000000000001101 补码
	
	
    //  1 的二进制位:>   00000000000000000000000000000001 原码
	//             :>  00000000000000000000000000000001 反码
	//             :>  00000000000000000000000000000001 补码

	// a 的补码    : >  00000000000000000000000000001101 补码
	// 1 的补码    : >  00000000000000000000000000000001 补码
	// 按位或      : >  00000000000000000000000000001101 补码

	a |= (1 << n - 1);	//这条语句让1的二进制位向左移动n位

	//假如移动到5号位: >   00000000000000000000000000010000 补码 16
	 
	// 或			: >  00000000000000000000000000001101 补码
	// 或			: >  00000000000000000000000000001101 反码
	// 或			: >  00000000000000000000000000001101 原码

	int i = (1 << n - 1); //当 n = 5 时结果为16 ,即移动到五号位
	printf("i值  i =%d\n",i);

	printf("改后 a =%d\n",a);	//当 n = 5 时结果为29,即移动到五号位

	//法一 把0改为1的位置,再改回来  

	a ^= (1 << n - 1);
	printf("\n法一\n改回 a =%d\n",a);	

	//法二 把0改为1的位置,再改回来
	int b = 29;						//这里直接创立一个变量为29

	//1的补码		 00000000000000000000000000000001 补码
	//假如移动到5号位  00000000000000000000000000010000 补码 16
	

	//1假如移动到5号位按位取反	11111111111111111111111111101111 补码
	 
	//b 			            00000000000000000000000000011101 原码 29	
	//							00000000000000000000000000011101 反码
	//							00000000000000000000000000011101 补码 
	//1							11111111111111111111111111101111 补码
	 
	//按位与后					00000000000000000000000000001101 补码
	//正数三码相同				00000000000000000000000000001101 反码
	//							00000000000000000000000000001101 原码 13
	b &= (~(1 << n-1));
	printf("\n法二\n改回 b =%d\n",b);	


	return 0;
}

结束语

加油吧!

未完持续……

  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

清风玉骨

爱了!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值