12

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

???1?0??

ビット 2 と 4 を交換したい (値を変更せず?に):

???0?1??

しかし、Cで1 回の操作でこれを行うにはどうすればよいでしょうか。

私はこの操作をマイクロコントローラーで毎秒何千回も実行しているため、パフォーマンスが最優先事項です。

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

4

8 に答える 8

30

Try:

x ^= 0x14;

That toggles both bits. It's a little bit unclear in question as you first mention swap and then give a toggle example. Anyway, to swap the bits:

x = precomputed_lookup [x];

where precomputed_lookup is a 256 byte array, could be the fastest way, it depends on the memory speed relative to the processor speed. Otherwise, it's:

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

EDIT: Some more information about toggling bits.

When you xor (^) two integer values together, the xor is performed at the bit level, like this:

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

so that bit 0 of the first value is xor'ed with bit 0 of the second value, bit 1 with bit 1 and so on. The xor operation doesn't affect the other bits in the value. In effect, it's a parallel bit xor on many bits.

Looking at the truth table for xor, you will see that xor'ing a bit with the value '1' effectively toggles the bit.

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

So, to toggle bits 1 and 3, write a binary number with a one where you want the bit to toggle and a zero where you want to leave the value unchanged:

00001010

convert to hex: 0x0a. You can toggle as many bits as you want:

0x39 = 00111001

will toggle bits 0, 3, 4 and 5

于 2009-06-11T14:59:27.943 に答える
11

ビットをいじることを使用して、1つの命令で2つのビットを「交換」することはできません(つまり、ビットは値ではなく場所を変更します)。

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

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

for (/*all my data values */) 
  newValue = lookup[oldValue];
于 2009-06-11T15:07:28.703 に答える
5

次のメソッドは、単一の C 命令ではありません。これは、別のちょっとした操作方法です。この方法は、 XOR を使用して個々のビットを交換することから簡略化されました。

Roddy's answerで述べたように、ルックアップ テーブルが最適です。使用したくない場合にのみ、これをお勧めします。これは実際にトグルだけでなくビットもスワップします (つまり、ビット 2 にあるものはすべて 4 になり、その逆も同様です)。

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

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

簡単な説明: 見たい 2 つのビットを取得して XOR し、値を に格納しますx。この値をビット 2 と 4 に戻す (そして一緒に OR する) と、XOR を元に戻したときにb2 つの元のビットが交換されるマスクが得られます。以下の表は、考えられるすべてのケースを示しています。

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

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

于 2009-06-11T16:24:32.403 に答える
4

これは最適化されていない可能性がありますが、動作するはずです:

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;
}
于 2009-11-04T06:07:35.990 に答える
2

以下の関数は、ビット 2 と 4 をスワップします。これを使用して、必要に応じてルックアップ テーブルを事前計算できます (スワップが 1 回の操作になるように)。

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;
}

わかりやすくするために、各操作を別の行に書きました。

于 2009-06-11T16:39:04.740 に答える
0

あなたの値がxであるとしましょう。つまり、x=???1?0??

この操作で 2 つのビットを切り替えることができます。

x = x ^ ((1<<2) | (1<<4));
于 2010-01-15T11:39:58.467 に答える
0
#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;
}
于 2013-11-13T10:29:57.443 に答える
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ビットの位置 (インデックス) で、下位ビットから数えてゼロから始まります。

例 ( n = ???1?0??) を使用すると、次のように関数を呼び出すことができます。

swap_bits(n, 2, 4);

根拠:ビットが異なる場合にのみビットを交換する必要があります(それが理由r != sです)。この場合、そのうちの 1 つが 1 で、もう 1 つが 0 です。その後、1 つのビット セット操作と 1 つのビット クリア操作を実行する必要があることに注意してください。

于 2015-10-06T08:08:18.873 に答える