質問

6 つの未知の値を含むバイトがあるとします。

???1?0??

ビット 2 と 4 を交換したいのですが (それなし いずれかを変更する ? 値):

???0?1??

しかし、これをどのように行うか ワンオペレーション Cで?

この操作はマイクロコントローラー上で 1 秒あたり数千回実行されるため、パフォーマンスが最優先されます。

これらのビットを「切り替える」のは問題ありません。これはビットを交換するのと同じではありませんが、切り替えは私の目的にはうまく機能します。

役に立ちましたか?

解決

試します:

x ^= 0x14;

の両方のビットをトグルします。それはあなたの最初の言及スワップとして質問に少し不明だし、その後、トグル例を与えます。とにかく、ビットを交換します。

x = precomputed_lookup [x];

precomputed_lookupが256バイト配列であり、最速の方法かもしれない、それはプロセッサ速度に対するメモリの速度に依存します。そうでなければ、それはです。

x = (x & ~0x14) | ((x & 0x10) >> 2) | ((x & 0x04) << 2);

編集:ビットをトグルに関するいくつかの詳細は、

。 あなたが一緒に(^)2つの整数値をXORする場合、

、XORは、このような、ビットレベルで実行されます。

for each (bit in value 1 and value 2)
   result bit = value 1 bit xor value 2 bit

最初の値のビット0がそのように第二値、ビット1とビット1とビット0とXORされているように。 XOR演算は、値の他のビットは影響を受けません。実際には、それは多くのビットのパラレルビットXORです。

XORの真理値表を見ると、あなたはそれが値を持つビットをXORし表示されます「1」効果的にビットをトグルます。

 a  b a^b
 0  0  0
 0  1  1
 1  0  1
 1  1  0

だから、ビット1と3を切り替えるには、あなたは少し切り替えたい1、あなたが変わらない値を残したいゼロで2進数を記述します:

00001010

進に変換:0x0Aを。あなたが必要な数のビットを切り替えることができます:

0x39 = 00111001

トグルするビット0、3、4および5

他のヒント

これは、ビットあいを使用して1つの命令で「スワップ」の2つのビット(すなわちビットが場所を変更しない値)できません。

あなたが実際にそれらを交換したい場合に最適なアプローチはおそらく、ルックアップテーブルです。これは、多くの「厄介な」変換にも当てはまります。

BYTE lookup[256] = {/* left this to your imagination */};

for (/*all my data values */) 
  newValue = lookup[oldValue];

次のメソッドは単一の C 命令ではなく、単なる別のビットいじりメソッドです。方法は以下から簡略化されました XOR を使用した個々のビットの交換.

に記載されているように、 ロディの答え, 、ルックアップテーブルが最適です。これは、使いたくない場合にのみお勧めします。これは実際に、単に切り替えるだけでなく、ビットも交換します (つまり、ビット 2 にあるものはすべて 4 に含まれ、その逆も同様です)。

  • b:元の値 - ???1?0??例えば
  • バツ:ただの一時的なもの
  • r:結果

    x = ((b >> 2) ^ (b >> 4)) & 0x01
    r = b ^ ((x << 2) | (x << 4))

簡単な説明:調べたい 2 つのビットを取得して XOR し、値を次の場所に保存します。 x. 。この値をビット 2 と 4 にシフトして戻す (そして一緒に OR 演算する) と、次のように XOR 演算して戻されたマスクが得られます。 b 元の 2 つのビットを交換します。以下の表は、考えられるすべてのケースを示しています。

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

これを完全にテストしたわけではありませんが、すぐに試したいくつかのケースではうまくいくようでした。

これは、最適化されないことがありますが、それは動作するはずます:

unsigned char bit_swap(unsigned char n, unsigned char pos1, unsigned char pos2)
{
    unsigned char mask1 = 0x01 << pos1;
    unsigned char mask2 = 0x01 << pos2;
   if ( !((n & mask1) != (n & mask2)) )
        n ^= (mask1 | mask2);
    return n;
}

以下の機能が(その結果スワッピングが単一の操作になる)必要に応じて、ルックアップテーブルを事前計算するためにこれを使用することができビット2および4を交換します。

unsigned char swap24(unsigned char bytein) {
    unsigned char mask2 = ( bytein & 0x04 ) << 2;
    unsigned char mask4 = ( bytein & 0x10 ) >> 2;
    unsigned char mask  = mask2 | mask4 ;
    return ( bytein & 0xeb ) | mask;
}

私はそれをより明確にするために別の行に各操作を書いています。

あなたの価値があると言うのxすなわち、X = ??? 1?0 ??

2ビットは、この操作によって切り替えることができます:

x = x ^ ((1<<2) | (1<<4));
#include<stdio.h>

void printb(char x) {
    int i;
    for(i =7;i>=0;i--) 
        printf("%d",(1 & (x >> i)));
    printf("\n");
}

int swapb(char c, int p, int q) {
    if( !((c & (1 << p)) >> p) ^ ((c & (1 << q)) >> q) )
        printf("bits are not same will not be swaped\n");
    else {
        c = c ^ (1 << p);
        c = c ^ (1 << q);
    }
    return c;
}

int main() 
{
    char c = 10;
    printb(c);
    c = swapb(c, 3, 1);
    printb(c);
    return 0;
}
void swap_bits(uint32_t& n, int a, int b) {
    bool r = (n & (1 << a)) != 0;
    bool s = (n & (1 << b)) != 0;

    if(r != s) {
        if(r) {
            n |= (1 << b);
            n &= ~(1 << a);
        }
        else {
            n &= ~(1 << b);
            n |= (1 << a);
        }
    }
}

n は交換する整数です。 a そして b は、スワップするビットの位置 (インデックス) であり、下位ビットから数えて 0 から始まります。

あなたの例を使用すると(n = ???1?0??)、次のように関数を呼び出します。

swap_bits(n, 2, 4);

理論的根拠:ビットが異なる場合にのみビットを交換する必要があります (これが理由です) r != s)。この場合、一方は 1、もう一方は 0 です。その後、実行したいのは 1 つだけであることに注意してください ビットセット 操作と1つ 少しはっきりした 手術。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top