基本思路
我们要先把想要交换的数的二进制位给写出来假如交换13的二进制位,13的二进制位是
0000 0000 0000 0000 0000 0000 0000 1101
然后写出偶数位的二进制数(偶数位是1的)
1010 1010 1010 1010 1010 1010 1010 1010
然后写出奇数位的二进制数(奇数位是1的)
0101 0101 0101 0101 0101 0101 0101 0101
最后把奇数位的二进制数,和偶数位的二进制数都和原来的数进行按位与然后奇数位向>>1向右移动1位就挪到了偶数位,偶数位向<<1向左移一位就挪到了奇数位,最后两个移动完的二进制位按位或就得到了奇数偶数位互换,像这张图
下面是代码
# include<stdio.h>
int main()
{
int num = 13;
printf("交换前\n");
for (int i = 0; i < 32; i++)
{
if (((num >> i) & 1) == 1)
{
printf("%d", 1);
}
else
{
printf("%d", 0);
}
}
printf("\n");
int temp = (num & 0x5555555555555555) << 1;
int temp2 = (num & 0xAAAAAAAA) >> 1;
int swap = temp | temp2;
int a = 0;
printf("交换后\n");
for (int i = 0; i < 32; i++)
{
if (((swap >> i) & 1) == 1)
{
printf("%d", 1);
}
else
{
printf("%d", 0);
}
}
return 0;
}
为什么打印出来是反的,那是由于在VS2022下是小端字节序存储是倒着存放的
0x5555555555555555就是奇数位
0xAAAAAAAA就是偶数位
define宏实现
同样用define宏定义也可以完成奇数偶数互换,下面是代码
# include<stdio.h>
# define SWAP(num) (num) = ((((num)&0xAAAAAAAA)>>1) | (((num)&0x5555555555555555)<<1))
int main()
{
int num = 13;
SWAP(num);
printf("%d", num);
return 0;
}
为什么define宏要打那么多括号呢,那是由于我们必须要确定好运算顺序和优先级,打括号保险一点,可以避免不可预料的后果