我是编程新手,我发现这种方法可以反转C中字节中的位:
//(10000011) -> (11000001)
unsigned char reverse(unsigned char b) {
b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
return b;
}
用户在回复this question时发布,但我无法理解它是如何运作的。这些常数意味着什么?
答案 0 :(得分:5)
查看上述数字的二进制表示可能会有所帮助:
0xF0: 11110000
0x0F: 00001111
0xCC: 11001100
0x33: 00110011
0xAA: 10101010
0x55: 01010101
第一对数字用于屏蔽掉并交换一个字节的前4位和后4位。
第二对屏蔽掉并交换一组4位的前2位和后2位。
第三对屏蔽并交换相邻的位对。
答案 1 :(得分:1)
代码首先交换&#34;半字节&#34;,即具有最低有效4位的最高有效4位。然后它将两个顶部订单对交换在一起,并将底部对一起交换;最后,它成对地交换2n和2n + 1位。
我将在尖括号中用它们的指数来表示b
这里的原始值的位(这只是我在这里使用的伪符号,不正确C);我使用o
来标记始终为0的任何位。所以一开始我们有
<76543210>
在第一次操作中没有
<76543210> & 0xF0
- &gt; <7654oooo>
<76543210> & 0x0F
- &gt; <oooo3210>
现在前者右移4位,后者左移4,因此我们得到
<7654oooo> >> 4
- &gt; <oooo7654>
<oooo3210> << 4
- &gt; <3210oooo>
最后这些是或者在一起,因此在声明之后
b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
b
的值是原始位的排列<32107654>
。
在第二个语句中,掩码0xCC
为11001100
二进制,0x33
为00110011
二进制;中间值是:
(<32107654> & 0xCC) >> 2
- &gt; <32oo76oo> >> 2
- &gt; <oo32oo76>
;和(<32107654> & 0x33) << 2
- &gt; <oo10oo54> << 2
- &gt; <10oo54oo>
。这些2或“一起”将导致排列<10325476>
。最后,掩码0xAA
为二进制10101010
,0x55
为01010101
。因此我们有
(<10325476> & 0xAA) >> 1
- &gt; <1o3o5o7o> >> 1
- &gt; <o1o3o5o7>
;和(<10325476> & 0x55) << 1
- &gt; <o0o2o4o6> << 1
- &gt; <0o2o4o6o>
这些或“一起”将导致排列<01234567>
,这与原始排列相反。
答案 2 :(得分:1)
所以这只是一点点转移。这些位按以下顺序排列:
76543210
现在,第一行,第一部分保持高位,将低位设置为0(掩码为0b11110000),将它们向右移动4。第二部分对低位(掩码为0b00001111)执行相同操作,并向左移位:
first line, first part: 7654xxxx => xxxx7654 (bits shift to the right)
first line, second part: xxxx3210 => 3210xxxx (bits shift to the left)
add them together: => 32107654
然后,第二行。相同的操作,不同的掩码(分别为0b11001100和0b00110011),32107654
:
second line, first part: 32xx76xx => xx32xx76 (bits shift to the right)
second line, second part: xx10xx54 => 10xx54xx (bits shift to the left)
add them together: => 10325476
第三行与其他掩码相同(分别为0b10101010和0b01010101),10325476
:
third line, first part: 1x3x5x7x => x1x3x5x7 (bits shift to the right)
third line, second part: x0x2x4x6 => 0x2x4x6x (bits shift to the left)
add them together: => 01234567
最后,我们最终采取行动:
76543210 => 01234567
答案 3 :(得分:0)
让我们对b
中的位进行编号,如下所示:
01234567
二进制文件中的 0xF0
为11110000
,0x0F
为00001111
。第一个赋值将最左边的4位向右移动,最右边的4位向左移动,然后将它们与OR
组合,结果是:
45670123
0xCC
为11001100
,0x33
为00110011
。当这些屏蔽位移位2位并组合时,结果为:
67452301
最后,0xAA
为10101010
,0x55
为01010101
。完成这些掩码和移位后,结果为:
76543210
瞧!这是相反的顺序。
注意,对于每对移位,位掩码是彼此相反的,并且移位的位数与掩码中1位序列的长度相同。因此,它们中的每一个都交换了一组大小为序列长度的位。
答案 4 :(得分:0)
您需要了解4个主要内容才能理解上述代码的含义。
& (AND) Bitwise Operator.
| (OR) Bitwise Operator.
>> (Right Shift Operator).
<< (Left Shift Operator).
幸运的是,我刚写了一篇详细的博客,解释了Number System and Bit Manipulation
的所有内容