题目描述:
写一个宏,可以将一个整数的二进制位的奇数位和偶数位交换。
题目分析:
相信大家都可以想到位运算如:按位异或,按位取反以及<<和>>等操作符,可是想到这些又能怎么样?还是没有思路。别慌,咱们要有有已知推未知的能力以及实在想不到可以举个例子,咱们现以1为例,众所周知,数字在系统中存储以32个比特位对吧,那1不就是以以下形式存储:
00000000 00000000 00000000 0000001
那奇数位与偶数位就换就是2了,那不就是扩大了二倍,然后你又进行验证,又搬出了5:
0000000 0000000 0000000 00000101
交换了奇数位与偶数位,果然扩大了二倍 ,然后你大喜过望,正准备书写代码,仅存的理智告诉你:现在还不是时候,这是不死心的你又拿出来13:
00000000 00000000 00000000 00001101
一交换,本以为会和之前一样,看到结果后却又饱受打击,为什么是14,这是为什么?为什么?
就在你苦恼之时,突然间灵光一闪,能不能把先确定这个数的奇偶位,然后运用位运算符得出答案。
-----------------------------------------TWO THOUSAND LATE-----------------------------------------------------
经过你潜心研究,终于得出了一份足以震惊世界的答案,于是你迫不及待地把答案公布出去,在万众瞩目的目光下,你清了清嗓子,缓缓说道:
交换奇偶位,需要先分别拿出奇偶位。既然是宏,分别拿出用循环不是很现实,那就用&这些位的方式来做。奇数位拿出,那就是要&上010101010101……,偶数位拿出,就是要&上101010101010……,对应十六进制分别是555……和aaa……,一般我们默认是32位整数,4位对应一位16进制就是8个5,8个a。通过& 0x55555555的方式拿出奇数位和& 0xaaaaaaa的方式拿出偶数位。奇数位左移一位就到了偶数位上,偶数位右移一位就到了奇数位上,最后两个数字或起来,就完成了交换。
※这个宏只能完成32位以内的整形,要想完成64位的,那就将5和a的数量翻倍即可。
你这一份发言虽使他们大受震撼,但他们说你口说无凭,随后,你这他们漫眼疑惑的目光中,在编译器敲下了能叫自己高光的代码:
代码实现:
#include <stdio.h>
#define SWEAP(n) n = (((n&0x55555555)<<1)+((n&0xaaaaaaaa)>>1))
int main()
{int n = 0;scanf("%d", &n);int ret = SWEAP(n);printf("%d", ret);return 0;
}
最后,你用你这神一般的代码赢得了阵阵掌声,赢了一切,从此出任CEO,迎娶白富美。在你成亲之日,觉得日光那么的耀眼,突然,你发现你这床上,你这开眼四望心茫然,不由得悲从中来,不可断绝。但你有察觉脑海中多了一段代码,觉得至少还有所收获,重新捡起了生活的信心!(此文纯属杜撰,为了帮助大家理解,不要当真!!!)
完!