如何仅使用位操作(无控制结构)将每个半字节的第0位和第3位切换为整数?为了解决这个问题,我需要创建什么样的面具?任何帮助,将不胜感激。例如,8(1000)变为1(0001)。
/*
* SwitchBits(0) = 0
* SwitchBits(8) = 1
* SwitchBits(0x812) = 0x182
* SwitchBits(0x12345678) = 0x82a4c6e1
* Legal Operations: ! ~ & ^ | + << >>
*/
int SwitchBits(int n) {
}
答案 0 :(得分:2)
代码:
#include <stdio.h>
#include <inttypes.h>
static uint32_t SwitchBits(uint32_t n)
{
uint32_t bit0_mask = 0x11111111;
uint32_t bit3_mask = 0x88888888;
uint32_t v_bit0 = n & bit0_mask;
uint32_t v_bit3 = n & bit3_mask;
n &= ~(bit0_mask | bit3_mask);
n |= (v_bit0 << 3) | (v_bit3 >> 3);
return n;
}
int main(void)
{
uint32_t i_values[] = { 0, 8, 0x812, 0x12345678, 0x9ABCDEF0 };
uint32_t o_values[] = { 0, 1, 0x182, 0x82A4C6E1, 0x93B5D7F0 };
enum { N_VALUES = sizeof(o_values) / sizeof(o_values[0]) };
for (int i = 0; i < N_VALUES; i++)
{
printf("0x%.8" PRIX32 " => 0x%.8" PRIX32 " (vs 0x%.8" PRIX32 ")\n",
i_values[i], SwitchBits(i_values[i]), o_values[i]);
}
return 0;
}
输出:
0x00000000 => 0x00000000 (vs 0x00000000)
0x00000008 => 0x00000001 (vs 0x00000001)
0x00000812 => 0x00000182 (vs 0x00000182)
0x12345678 => 0x82A4C6E1 (vs 0x82A4C6E1)
0x9ABCDEF0 => 0x93B5D7F0 (vs 0x93B5D7F0)
注意使用uint32_t
来避免带有符号整数的符号位的未定义行为。
答案 1 :(得分:1)
要获得一点,您可以使用AND将其掩盖。要获得最低位,例如:
x & 0x01
考虑AND如何工作:必须设置两个位。由于我们与1进行AND运算,除第一个之外的所有位必须为0,因为它们在0x01中为0。最低位将为0或1,具体取决于x
中的内容;换句话说,最低位将是x
中的最低位,这是我们想要的。目测:
x = abcd
AND 1 = 0001
--------
000d
(其中abcd
表示这些位中的位;我们不知道它们是什么)
要将它移动到第3位,只需移动它:
(x & 0x01) << 3
视觉上,再次:
x & 0x01 = 000d
<< 3
-----------
d000
要添加它,首先,我们需要清除x
中的那个位置。我们再次使用AND:
x & ~0x08
在这里,我们反转0x08
(二进制为1000):这意味着除了第3位之外的所有位都已设置,当我们与x
进行比较时,我们得到x
除了那个位。
在视觉上,
0x08 = 1000
(invert)
-----------
0111
AND x = abcd
------------
0bcd
与OR结合:
(x & ~0x08) | ((x & 0x01) << 3)
在视觉上,
x & ~0x08 = 0bcd
| ((x & 0x01) << 3) = d000
--------------------------
dbcd
现在,这只会将第0位移到第3位,只会覆盖第3位。我们仍需要执行第3位→0位。这只是另一位:
x & 0x08 >> 3
我们需要清除它的位置:
x & ~0x01
我们可以结合两个清算部分:
x & ~0x09
然后:
(x & ~0x09) | ((x & 0x01) << 3) | ((x & 0x08) >> 3)
那当然只处理最低的半字节。我将把其他人留作练习。
答案 2 :(得分:1)
尝试以下代码。在这里你应该知道按位运算符来实现和纠正位置。还需要了解维护,转移和切换基本属性。
#include<stdio.h>
#define BITS_SWAP(x) x=(((x & 0x88888888)>>3) | ((x & 0x11111111)<<3)) | ((x & ~ (0x88888888 | 0x11111111)))
int main()
{
int data=0;
printf("enter the data in hex=0x");
scanf("%x",&data);
printf("bits=%x",BITS_SWAP(data));
return 0;
}
OP
vinay @ vinay-VirtualBox:〜/ c_skill $ ./a.out
在hex=0x1
bits=8
vinay @ vinay-VirtualBox:〜/ c_skill $ ./a.out
在hex=0x812
中输入数据
bits=182
vinay @ vinay-VirtualBox:〜/ c_skill $ ./a.out
在hex=0x12345678
中输入数据
bits=82a4c6e1
维奈@维奈-VirtualBox的:〜/ c_skill $
答案 3 :(得分:1)
代码:
unsigned SwitchBits(unsigned n) {
return ((n << 3) & 0x88888888) | ((n >> 3) & 0x11111111) | (n & 0x66666666);
}
另外,如果你想要非常聪明。它可以通过两个较少的操作完成,但由于一些指令之间的依赖性,这实际上可能不会更快。
0
,如果它们不同则为1
。9
,这将保持低位,并将其复制到高位。代码:
unsigned SwitchBits(unsigned n) {
return ((((n >> 3) ^ n) & 0x11111111) * 0x9) ^ n;
}
答案 4 :(得分:1)
尝试xor swap的这个变种:
uint32_t switch_bits(uint32_t a){
static const mask = 0x11111111;
a ^= (a & mask) << 3;
a ^= (a >> 3) & mask;
a ^= (a & mask) << 3;
return a;
}