Domanda

Diciamo che ho un byte con sei valori sconosciuti:

???1?0??

e voglio scambiare bit 2 e 4 ( senza cambiare qualsiasi valore ?):

???0?1??

Ma come faccio a fare questo in una sola operazione in C?

sto eseguendo questa operazione migliaia di volte al secondo su un microcontrollore quindi le prestazioni è la priorità assoluta.

Sarebbe bene a "passare" questi bit. Anche se questo non è lo stesso di scambiare i bit, commutazione avrebbe funzionato bene per i miei scopi.

È stato utile?

Soluzione

Prova:

x ^= 0x14;

che attiva entrambi i bit. E 'un po' poco chiaro in questione, come si primo swap menzione e poi fare un esempio a ginocchiera. In ogni caso, per scambiare i bit:

x = precomputed_lookup [x];

dove precomputed_lookup è un array di 256 byte, potrebbe essere il modo più veloce, dipende dalla velocità di memoria rispetto alla velocità del processore. In caso contrario, si tratta di:

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

EDIT:. Alcuni ulteriori informazioni sulla commutazione bit

Quando si XOR (^) due valori interi insieme, lo XOR viene eseguita a livello di bit, in questo modo:

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

in modo che il bit 0 del primo valore viene esservi effettuato lo XOR con il bit 0 del secondo valore, il bit 1 con 1 bit e così via. L'operazione xor non influenza gli altri bit del valore. In effetti, si tratta di un XOR bit in parallelo su molti bit.

Guardando la tabella di verità per XOR, vedrete che xor'ing un po 'con il valore '1' consente di passare in modo efficace il bit.

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

Quindi, per attivare o disattivare i bit 1 e 3, scrivere un numero binario con uno in cui si desidera il bit per alternare e uno zero in cui si desidera lasciare il valore invariato:

00001010

convertire in esadecimale: 0x0a. È possibile attivare il maggior numero di bit come si vuole:

0x39 = 00111001

farà passare i bit 0, 3, 4 e 5

Altri suggerimenti

Non puoi "swap" due bit (cioè i bit cambiano i luoghi, non di valore) in una singola istruzione utilizzando bit-giocherellare.

L'approccio ottimale se si vuole scambiare loro davvero è probabilmente una tabella di ricerca. Questo vale per molte trasformazioni 'scomode'.

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

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

Il seguente metodo non è una singola istruzione C, è solo un altro metodo po 'armeggiare. Il metodo è stato semplificato da scambi singoli bit con XOR .

Come affermato nella risposta di Roddy , una tabella di ricerca sarebbe meglio. Suggerisco solo questo nel caso in cui non ha voluto usare uno. Ciò possa scambiare bit inoltre, non solo alternare (cioè, ciò che è in bit 2 sarà in 4 e viceversa).

  • b:? Il vostro valore originario - ??? 1 0 ?? per esempio
  • x: solo un temp
  • R: il risultato

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

spiegazione rapida: ottenere i due bit che si desidera guardare e li XOR, memorizzare il valore di x. Spostando questo valore di nuovo al bit 2 e 4 (e OR'ing insieme) si ottiene una maschera che quando XORed indietro con b cambierà i vostri due bit originali. La tabella seguente mostra tutti i casi possibili.

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

non ho la prova pienamente questo, ma per i pochi casi che ho provato subito tutto sembrava funzionare.

Questo potrebbe non essere ottimizzato, ma dovrebbe funzionare:

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

La funzione qui sotto scambierà bit 2 e 4. È possibile utilizzare questo per precompute una tabella di ricerca, se necessario (in modo che scambio diventa una singola operazione):

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

ho scritto ogni operazione su una riga separata per renderlo più chiaro.

Dite il vostro valore è x cioè, x = ??? 1? 0 ??

I due bit possono essere attivate con questa operazione:

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 è il numero intero che si desidera essere scambiati in, a e b sono le posizioni (indici) dei bit che si desidera essere scambiati, contando dal bit meno significativo e partendo da zero.

Usando il tuo esempio (n = ???1?0??), si avrebbe chiamato la funzione come segue:

swap_bits(n, 2, 4);

Motivazioni : è sufficiente scambiare i bit se sono diversi (è per questo che r != s). In questo caso, uno di loro è 1 e l'altro è 0. Dopo di che, basta notare che si vuole fare esattamente un impostato il bit il funzionamento e una po 'chiaro il funzionamento.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top