位运算符那些事(典型例题)

位运算符那些事(典型例题)

 
 

目录

一、常见的位运算符的结论

二、设置一个函数找出一个数组中的一个不同值

三、设置一个函数找出一个数组中的两个不同值

四、写一个宏,可以将一个整数的奇偶位交换

 


 

一、常见的位运算符的结论

  • 结论一:某个数和1按位与(&)可以得到某个数的二进制的个位

证明: 在这里插入图片描述
 

  • 结论二:某个数和0按位异或(^)就是本身

证明:
在这里插入图片描述

 

  • 结论三:相同的数按位异或(^)就是0

证明: 在这里插入图片描述

 

  • 结论四: 按位异或(^)符合交换律

证明: 在这里插入图片描述

返回目录

 


 

二、设置一个函数找出一个数组中的一个不同值

基本思路:将数组中的每一个数按位与(&),得到的数就是那个不同的值
因为一个数组只有一个不同值,根据结论三结论四可知:所有的相同的数即使没
有顺序按位异或(^)的结果为0,然后根据结论二按位异或(^)的结果就是所求的不同值

#include <stdio.h>
int Diff(int arr[], int sz)
{
	int i = 0;
	int n = 0;
	for (i = 0; i < sz; i++)
	{
		n ^= arr[i];//每一个数组元素按位与一起
	}
	return n;
}

int main()
{
	int arr[15] = { 0,1,2,3,4,5,6,8,0,1,2,3,4,5,6 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	int ret = Diff(arr, sz);
	printf("%d\n", ret);
	return 0;
}

运行结果:
在这里插入图片描述

返回目录

 


 

三、设置一个函数找出一个数组中的两个不同值

基本思路:

1.先将数组中所有的元素异或 = 两个不同元素的异或

2.找出两个不同数中第一个不同的位,通过这个条件将他们分为两组,一个组是这个位为0;另一组是这个位为1

3.将两个不同的元素分到不同的两个组并分别异或

图例:
在这里插入图片描述

#include <stdio.h>
void Find(int arr[], int sz, int* px, int* py)
{
	//1.先将数组中所有的元素异或 = 两个不同元素的异或
	int ret = 0;
	int i = 0;
	int pos = 0;
	int tar1 = 0;
	int tar2 = 0;
	for (i = 0; i < sz; i++)
	{
		ret ^= arr[i];
	}
	//2.找出两个不同数中第一个不同的位
	for (i = 0; i < 32; i++)
	{
		if (((ret >> i) & 1) == 1)//用到了结论一,结果等于1说明了找出两个不同数中第一个不同的位
		{
			pos = i;
			break;
		}
	}
	//3.分组并异或
	for (i = 0; i < sz; i++)
	{
		if (((arr[i] >> pos) & 1) == 1)
		{
			tar1 ^= arr[i];
		}
		else
		{
			tar2 ^= arr[i];
		}
	}
	*px = tar1;
	*py = tar2;
}

int main()
{
	int x = 0;
	int y = 0;
	int arr[] = { 1,3,4,5,7,8,1,3,4,5 };
	int sz = sizeof(arr) / sizeof(arr[10]);
	Find(arr, sz, &x, &y);//将x, y的地址传过去,把两个不相同的数带回来
	printf("%d\n", x);
	printf("%d\n", y);
	return 0;
}

运行结果:
在这里插入图片描述

返回目录

 


 

四、写一个宏,可以将一个整数的奇偶位交换

基本思路
1.有一个整数num,取出偶数位num & 0xaaaaaaaa
2.取出奇数位num & 0x55555555
3.偶数右移一位, 奇数左移一位
4.两数相加

取出偶数位num & 0xaaaaaaaa:
在这里插入图片描述

 

取出奇数位num & 0x55555555:
在这里插入图片描述
 
奇数位加偶数位等于原整数:
在这里插入图片描述

#include <stdio.h>
#define SWITCH(num) (((num & 0xaaaaaaaa)>>1) + ((num & 0x55555555)<<1))
                      //取出偶数右移                 //取出奇数左移                      
int main()
{
	int num = 10;
	int ret = SWITCH(num);
	printf("%d\n", ret);
	return 0;
}

运行结果:
在这里插入图片描述

返回目录

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值