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を使わずにこのコードを 1 行で書く方法はありますか

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 の第一人者ではない人々 (そしておそらく今から 6 か月後にはあなた自身) が、1 行のマルチビット演算子のバリアントよりもソース コードをよりよく理解できるようになるということです。

于 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 に答える