Nat*_*ray 12 c bit-manipulation arduino bit
假设我有一个包含六个未知值的字节:
???1?0??
Run Code Online (Sandbox Code Playgroud)
我想交换第2和第4位(不改变任何?值):
???0?1??
Run Code Online (Sandbox Code Playgroud)
但是如何在C 中的一次操作中执行此操作?
我在微控制器上每秒执行此操作数千次,因此性能是首要任务.
可以"切换"这些位.即使这与交换位不同,切换也可以用于我的目的.
Ski*_*izz 30
尝试:
x ^= 0x14;
Run Code Online (Sandbox Code Playgroud)
这会切换两个位.当你第一次提到交换然后给出一个切换示例时,这有点不清楚.无论如何,交换位:
x = precomputed_lookup [x];
Run Code Online (Sandbox Code Playgroud)
其中precomputed_lookup是一个256字节的数组,可能是最快的方式,它取决于相对于处理器速度的内存速度.否则,它是:
x = (x & ~0x14) | ((x & 0x10) >> 2) | ((x & 0x04) << 2);
Run Code Online (Sandbox Code Playgroud)
编辑:有关切换位的更多信息.
当xor(^)将两个整数值放在一起时,xor在位级执行,如下所示:
for each (bit in value 1 and value 2)
result bit = value 1 bit xor value 2 bit
Run Code Online (Sandbox Code Playgroud)
因此,第一个值的第0位与第二个值的第0位xor'ed,第1个第1位的第1位依此类推.xor操作不会影响值中的其他位.实际上,它是许多位上的并行位xor.
查看xor的真值表,你会看到xor'ing有点值'1'有效地切换了这个位.
a b a^b
0 0 0
0 1 1
1 0 1
1 1 0
Run Code Online (Sandbox Code Playgroud)
因此,要切换位1和3,请写入一个二进制数,其中一个位于您希望位切换的位置,而零位则要保持值保持不变:
00001010
Run Code Online (Sandbox Code Playgroud)
转换为十六进制:0x0a.您可以根据需要切换多个位:
0x39 = 00111001
Run Code Online (Sandbox Code Playgroud)
将切换位0,3,4和5
Rod*_*ddy 11
您不能使用bit-fiddling在单个指令中"交换"两个位(即位改变位置,而不是值).
如果你想真正交换它们的最佳方法可能是查找表.这适用于许多"尴尬"的转变.
BYTE lookup[256] = {/* left this to your imagination */};
for (/*all my data values */)
newValue = lookup[oldValue];
Run Code Online (Sandbox Code Playgroud)
以下方法不是单个C指令,它只是另一个小巧的方法.通过使用XOR交换单个位简化了该方法.
如Roddy的回答所述,查找表最好.我只是建议你,以防你不想使用它.这也确实会交换位,而不仅仅是切换(也就是说,位2中的任何内容都将在4中,反之亦然).
r:结果
x =((b >> 2)^(b >> 4))&0x01
r = b ^((x << 2)|(x << 4))
快速解释:获取您想要查看的两个位并对它们进行异或,将值存储到x.通过将此值移回第2位和第4位(以及同时进行"或"运算),您将获得一个掩码,当与其进行异或时b将交换您的两个原始位.下表显示了所有可能的情况.
bit2: 0 1 0 1
bit4: 0 0 1 1
x : 0 1 1 0 <-- Low bit of x only in this case
r2 : 0 0 1 1
r4 : 0 1 0 1
Run Code Online (Sandbox Code Playgroud)
我没有对此进行全面测试,但对于少数情况我很快就尝试了它似乎有效.