如何在二进制数中交换每2位?

时间:2013-09-18 19:00:13

标签: c bit-manipulation

我正在研究这个编程项目,其中一部分是使用按位运算符编写一个函数,每两位切换一次。我已经提出了一种梳理算法来实现这一点,但它只适用于无符号数字,任何想法我如何才能使它与带符号的数字一起工作?我完全被这个困扰了。这是我到目前为止所拥有的:

        // Mask 1 - For odd bits
    int a1 = 0xAA; a1 <<= 24;
    int a2 = 0xAA; a2 <<= 16;
    int a3 = 0xAA; a3 <<= 8;
    int a4 = 0xAA;
    int mask1 = a1 | a2 | a3 | a4;

    // Mask 2 - For even bits
    int b1 = 0x55; b1 <<= 24;
    int b2 = 0x55; b2 <<= 16;
    int b3 = 0x55; b3 <<= 8;
    int b4 = 0x55;
    int mask2 = b1 | b2 | b3 | b4;

    // Mask Results
    int odd = x & mask1;
    int even = x & mask2;

    int newNum = (odd >> 1) | (even << 1);

    return newNum;

通过“或”变量一起手动创建掩码是因为可以使用的唯一常量介于0x00-0xFF之间。

4 个答案:

答案 0 :(得分:3)

问题是odd >> 1将使用负数进行签名扩展。只需执行另一个and即可消除重复的位。

int newNum = ((odd >> 1) & mask2) | (even << 1);

答案 1 :(得分:2)

最小化运算符并注意符号扩展问题,提供:

int odd = 0x55;
odd |= odd << 8;
odd |= odd << 16;

int newnum =   ((x & odd) << 1 )  // This is (sort of well defined)
             | ((x >> 1) & odd);  // this handles the sign extension without
                                  // additional & -operations

但要注意的是:bit twiddling通常只适用于无符号整数。

答案 2 :(得分:0)

当您右移有号码时,该标志也将被延长。这称为sign extension。通常,当您处理位移时,您希望使用无符号数字。

答案 3 :(得分:0)

通过一次处理一个字节来最小化常量的使用:

unsigned char* byte_p;
unsigned char byte;
int ii;
byte_p = &x;   
for(ii=0; ii<4; ii++) {
  byte = *byte_p;
  *byte_p = ((byte & 0xAA)>>1) | ((byte & 0x55) << 1);
  byte_p++;
}     

最小化操作并在0x000xFF之间保持常量:

unsigned int comb = (0xAA << 8) + 0xAA;
comb += comb<<16;
newNum = ((x & comb) >> 1) | ((x & (comb >> 1)) << 1);

10次操作。

刚看到上面的评论,并意识到这正在实施(或多或少)@akisuihkonen提出的一些建议。所以请考虑一下这个问题!