逆向欲反向二进制使用位运算符
unsigned short gf_t = 44 // = 00101100
在00110100
在C语言无符号短矢量。我如何能够使用按位运算符?
pdta:我的电脑有32位模式。
逆向欲反向二进制使用位运算符
unsigned short gf_t = 44 // = 00101100
在00110100
在C语言无符号短矢量。我如何能够使用按位运算符?
pdta:我的电脑有32位模式。
如有疑问,请参阅Bit Twiddling Hacks page。事实上,你可以找到一个很简单的算法,你想要做什么......
反位的明显的方式
unsigned int v; // input bits to be reversed unsigned int r = v; // r will be reversed bits of v; first get LSB of v int s = sizeof(v) * CHAR_BIT - 1; // extra shift needed at end for (v >>= 1; v; v >>= 1) { r <<= 1; r |= v & 1; s--; } r <<= s; // shift when v's highest bits are zero
2004年10月15日,迈克尔·Hoisie中指出的错误原始版本。 Randal E. Bryant建议在2005年5月3日删除额外的操作。Behdad Esfabod提出了一个稍微的改变,在2005年5月18日消除了该循环的一次迭代。然后,2007年2月6日,Liyong Zhou提出了一个更好的版本,而v不是0,所以不要遍历所有位,而是尽早停止。
但是,也有一些漂亮的方法记录在那里。你可以看看这些,并尝试了解他们的学习:-)例如,这里是一个特别有趣的形式...
反向5 * LG电子(N)操作并行的N位数量:
unsigned int v; // 32-bit word to reverse bit order // swap odd and even bits v = ((v >> 1) & 0x55555555) | ((v & 0x55555555) << 1); // swap consecutive pairs v = ((v >> 2) & 0x33333333) | ((v & 0x33333333) << 2); // swap nibbles ... v = ((v >> 4) & 0x0F0F0F0F) | ((v & 0x0F0F0F0F) << 4); // swap bytes v = ((v >> 8) & 0x00FF00FF) | ((v & 0x00FF00FF) << 8); // swap 2-byte long pairs v = (v >> 16 ) | (v << 16);
注意,如果sizeof(unsigned short) * CHAR_BIT
是16
,适当的使用将只需要前4个换位 - 见如下:
unsigned short v;
// swap odd and even bits
v = ((v >> 1) & 0x5555) | ((v & 0x5555) << 1);
// swap consecutive pairs
v = ((v >> 2) & 0x3333) | ((v & 0x3333) << 2);
// swap nibbles ...
v = ((v >> 4) & 0x0F0F) | ((v & 0x0F0F) << 4);
// swap bytes
v = ((v >> 8) & 0x00FF) | ((v & 0x00FF) << 8);
这就是说,为什么不只是使用uint16_t
(如果它是可用的)?
这里是工作的例子(见ideone):
#include <stdio.h>
#include <assert.h>
#include <stdint.h>
inline uint16_t reverse(uint16_t v) {
v = ((v >> 1) & 0x5555) | ((v & 0x5555) << 1); /* swap odd/even bits */
v = ((v >> 2) & 0x3333) | ((v & 0x3333) << 2); /* swap bit pairs */
v = ((v >> 4) & 0x0F0F) | ((v & 0x0F0F) << 4); /* swap nibbles */
v = ((v >> 8) & 0x00FF) | ((v & 0x00FF) << 8); /* swap bytes */
return v;
}
main() {
uint16_t gf_t = 44;
printf("%hu\n", reverse(gf_t));
}
通常你用and
输入1来得到它的LSB。 Or
即成结果。将结果左移一点,右输入一点。重复总共32次迭代。
你可以像下面这样做(v
是一个16位数字):
v = ((v >> 1) & 0x5555) | ((v & 0x5555) << 1);
v = ((v >> 2) & 0x3333) | ((v & 0x3333) << 2);
v = ((v >> 4) & 0x0F0F) | ((v & 0x0F0F) << 4);
v = ((v >> 8) & 0x00FF) | ((v & 0x00FF) << 8);
你可以找到更多的花样这样here。这是一个link to ideone with this code snippet。
如果你想使这个意义上说,写在本例中使用的 “幻数” 的二进制表示:
0x5555
是0101010101010101
0x3333
是0011001100110011
0x0F0F
被0000111100001111
0x00FF
是0000000011111111
&
操作清除“不需要的”位;这些移位将所需部分重新定位在由掩蔽操作打开的“零间隙”上,最后|
重新组合这两个部分。
二进制文件是0000000000101100 - 短中有16位。
//包括去这里
int main() {
无符号短gf_t = 44; cout < <十六进制< < gf_t < < endl;
unsigned short gf_r = 0;
for (int iter = 0; iter < sizeof(short) * 8; ++iter)
{
unsigned short tmp = gf_t;
tmp = tmp & 1;
gf_r = (gf_r << 1) | tmp;
gf_t = gf_t >> 1;
}
cout << hex << gf_r << endl;
}
[你尝试过什么?](http://whathaveyoutried.com)这是功课? – 2012-09-10 19:05:33
在你的例子中,你想得到的结果叫做'交换半字节'。去谷歌上查询。 – fork0