4

我已经编写了一个用于交换位位置(源位和目标位)的代码..它工作正常..但是有没有优化的代码来做到这一点?

int bit_swap(int num, int sbit, int dbit)
{
if(num & (1 << sbit) == num & (1 << dbit))
return num;
else
return (num ^ ((1 << sbit) | (1 << dbit)));
}

这里.. num 是输入数字.. sbit 是源位位置,dbit 是目标位位置..

有没有办法在不使用ifelse的情况下在一行中编写此代码

4

3 回答 3

12

你犯了一个经典的错误,认为 C 中的行越少意味着代码越优化。

您应该真正检查汇编程序输出并分析您的代码,看看它是否是一个实际的瓶颈。

我倾向于做的是首先优化可读性,然后只有在它成为问题时才攻击性能。因此,一个更具可读性的解决方案(在我看来并不那么谦虚)是这样的:

unsigned int bit_swap (unsigned int num, unsigned int pos1, unsigned int pos2) {
    // Swapping identical bit positions is a no-op.

    if (pos1 == pos2)
        return num;

    // Get masks from bit positions.

    unsigned int mask1 = 1 << pos1;
    unsigned int mask2 = 1 << pos2;

    // Get bit truth values.

    int bit1_was_set = ((num & mask1) != 0);
    int bit2_was_set = ((num & mask2) != 0);

    // Clear and set first bit (set only if second bit was originally set).

    num = num & ~mask1;
    if (bit2_was_set)
        num = num | mask1;

    // Do the same for other bit.

    num = num & ~mask2;
    if (bit1_was_set)
        num = num | mask2;

    // Return the value with swapped bits.

    return num;
}

尽管行数比您的方法多得多,但您很可能会发现现在可用的疯狂优化的编译器会在幕后为您提供类似的代码。

您几乎肯定发现,非 C 专家(可能还有您自己,六个月后)将能够比单行多位运算符变体更好地理解您的源代码。

于 2013-01-02T06:03:52.700 回答
6

无条件版本。

int bit_swap(int num, int sbit, int dbit)
{
    int sval = !!(num & (1 << sbit));  // sets to 1 iff the s-bit is already set
    int dval = !!(num & (1 << dbit));  // sets to 1 iff the d-bit is already set

    int xorval = (sval ^ dval); // sets to 1 if (sval != dval), otherwise 0

    // so if xorval is 1, then it will toggle the bits at the S and D positions
    // otherwise, the expression below evalutes to "num" that was passed in
    return (num ^ ((xorval << sbit) | (xorval << dbit)));
}
于 2013-01-02T06:36:37.503 回答
2

我想出了

unsigned swapBits(unsigned num, int sbit, int dbit)
{
  return ( num &               // All bits
    ~((1<<sbit) | (1<<dbit)))  // Except sbit and dbit
    | (((num>>sbit)&1)<<dbit)  // but with sbit moved to dbit
    | (((num>>dbit)&1)<<sbit); // and with dbit moved to sbit
}

我确实有一个 ARM 的想法,它的成本低廉。

于 2013-03-13T16:08:00.267 回答