位运算符那些事(典型例题)
目录
一、常见的位运算符的结论
二、设置一个函数找出一个数组中的一个不同值
三、设置一个函数找出一个数组中的两个不同值
四、写一个宏,可以将一个整数的奇偶位交换
一、常见的位运算符的结论
- 结论一:某个数和1按位与(&)可以得到某个数的二进制的个位
证明:
证明:
证明:
证明:
返回目录
二、设置一个函数找出一个数组中的一个不同值
基本思路:将数组中的每一个数按位与(&),得到的数就是那个不同的值
因为一个数组只有一个不同值,根据结论三、结论四可知:所有的相同的数即使没
有顺序按位异或(^)的结果为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;
}
运行结果: