要写一个宏实现将一个整数的二进制位的奇数位和偶数位交换,我们首先要分析如何将一个整数的二进制位的奇数位和偶数位交换
以下以整数7为例
7的二进制:
0000 0000 0000 0000 0000 0000 0000 0111 7
奇数位与偶数位交换后为:
0000 0000 0000 0000 0000 0000 0000 1011 11
📖分析:
交换奇数位和偶数位可以分为两步:
1️⃣奇数位放到偶数位
实现如下:
奇数位不变,偶数位置0,整体左移一位
偶数位置0:0000 0000 0000 0000 0000 0000 0000 0101
左移一位: 0000 0000 0000 0000 0000 0000 0000 1010
此时,已将所有奇数位移动到了偶数位上
2️⃣偶数位放到奇数位
偶数位不变,奇数位置0,整体右移一位
偶数位置0:0000 0000 0000 0000 0000 0000 0000 0010
右移一位: 00000 0000 0000 0000 0000 0000 0000 001
此时,已将所有偶数位移动到了奇数位上
如何将所有偶数位/奇数位置0:
偶数位置零:
0&任何数都为0,所以给所有偶数位&0,为了保证奇数位不变,给所有奇数位&1
所以偶数位置0只需要给原数&10101010 10101010 10101010 10101010
即十六进制数:0x aaaaaaaa
同理,奇数位置0:
给原数& 01010101 01010101 01010101 01010101
即十六进制数:0x 55555555
📖Note:
如何判断左移还是右移?
从最低位看,最低位为一个奇数位,次低位为偶数位,交换时,最低位与次低位交换
奇数位放到偶数位时:即最低位放到次低位上,为向左移
偶数位放到奇数位时:即次低位放到最低位上,为向右移
奇数位移动: 0000 0000 0000 0000 0000 0000 0000 1010
偶数位移动: 00000 0000 0000 0000 0000 0000 0000 001
奇数位与偶数位的分别操作之后,如何整合?
将两次操作得到的数据相加即可;
进行奇数位的操作时,偶数位全被置为0,奇数位的数据有效
进行偶数位的操作时,奇数位全被置为0,偶数位的数据有效
实现:
#include<stdio.h>
#define SWAP(n) (((n&0xaaaaaaaa)>>1) + ((n&0x55555555)<<1))
int main()
{
int n = 7;
int m = SWAP(n);
printf("%d %d\n", n, m);
return 0;
}
📖Note:
左移操作符会改变变量本身的值,但是#define定义的宏在预处理阶段完成替换,即在预处理阶段#define定义的宏中,n都被替换成7,先替换再计算时,n的值并不会被改变,也不会影响计算结果