Pregunta

Vamos a decir que tengo un byte con seis valores desconocidos:

???1?0??

y quiero intercambiar los bits 2 y 4 ( sin cambiar cualquiera de los valores ?):

???0?1??

Pero ¿cómo voy a hacer esto en una sola operación en C?

Estoy de realizar esta operación miles de veces por segundo en un microcontrolador lo que el rendimiento es la máxima prioridad.

Sería preciso para "cambiar" estos bits. A pesar de que esto no es lo mismo que el canje de los bits, alternar funcionaría bien para mis propósitos.

¿Fue útil?

Solución

Probar:

x ^= 0x14;

Esto alterna ambos bits. Es un poco claro de que se trata a medida que la primera mención de intercambio y luego dar un ejemplo de palanca. De todos modos, para intercambiar los bits:

x = precomputed_lookup [x];

donde precomputed_lookup es una matriz de 256 byte, podría ser la forma más rápida, depende de la velocidad de la memoria con relación a la velocidad del procesador. De lo contrario, es:

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

EDIT:. Algunos más información acerca de alternar los bits

Cuando XOR (^) dos valores enteros juntos, el XOR se lleva a cabo a nivel de bits, como esto:

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

de modo que el bit 0 del primer valor se xor'ed con el bit 0 del segundo valor, el bit 1 el bit 1 y así sucesivamente. La operación XOR no afecta a los otros bits en el valor. En efecto, se trata de un XOR bit paralelo en muchos bits.

En cuanto a la tabla de verdad para XOR, se verá que xor'ing un poco con el valor '1' alterna de manera efectiva el bit.

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

Por lo tanto, para cambiar los bits 1 y 3, escribir un número binario con un uno en el que desea el bit para alternar y un cero en el que desea dejar el valor sin cambios:

00001010

convertir a hexadecimal: 0x0a. Puede alternar tantos bits como desee:

0x39 = 00111001

alternará bits 0, 3, 4 y 5

Otros consejos

No se puede "Swap" dos bits (es decir, los bits cambian de lugar, no valor) en una sola instrucción utilizando el bit-tocar el violín.

El enfoque óptimo si se desea intercambiar realmente les es probablemente una tabla de consulta. Esto es cierto para muchas transformaciones 'incómodas'.

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

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

El siguiente método no es una sola instrucción C, es sólo otro método poco tocar el violín. El método se ha simplificado de Intercambio de bits individuales con XOR .

Como se dijo en respuesta de Roddy , una tabla de consulta sería lo mejor. Sólo sugiero esto en caso de que no quería utilizar uno. De hecho, esto también intercambiar trozos, no sólo cambiar (es decir, lo que está en el bit 2 será de 4 y viceversa).

  • b:? Su valor original - ??? 1 0 ?? por ejemplo
  • x: sólo un temp
  • r: el resultado

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

explicación rápida: obtener los dos bits que desea mirar y XOR ellos, almacenar el valor de x. Al cambiar este valor de nuevo a los bits 2 y 4 (y OR'ing juntos) se obtiene una máscara que cuando XOR de vuelta con b intercambiará sus dos bits originales. La siguiente tabla muestra todos los casos posibles.

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

no he probado esto completamente, pero para los pocos casos en que probé rápido que parecía funcionar.

Esto no puede ser optimizado, pero debería funcionar:

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 siguiente función intercambiará los bits 2 y 4. Usted puede usar esto para calcular previamente una tabla de búsqueda, si es necesario (para que el intercambio se convierte en una sola operación):

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

escribí cada operación en una línea separada para hacerlo más claro.

Digamos que su valor es x es decir, x = ??? 1? 0 ??

Los dos bits se pueden activar por esta operación:

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 es el número entero que desea ser intercambiado en, a y b son las posiciones (indicadores) de los bits que desea ser intercambiado, a contar desde el bit menos significativo y a partir de cero.

Usando su ejemplo (n = ???1?0??), que se podría llamar la función de la siguiente manera:

swap_bits(n, 2, 4);

Justificación : sólo es necesario cambiar los bits si son diferentes (por eso r != s). En este caso, uno de ellos es 1 y el otro es 0. Después de eso, simplemente observe que quiere hacer exactamente un conjunto de bits Operación y uno poco clara operación.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top