Pergunta

Vamos dizer que tenho um byte com seis valores desconhecidos:

???1?0??

e eu quero pedaços de swap 2 e 4 ( sem mudar qualquer um dos valores ?):

???0?1??

Mas como eu faria isso em uma operação em C?

Eu estou realizando esta operação milhares de vezes por segundo em um microcontrolador por isso o desempenho é a prioridade.

Seria bom para "toggle" esses bits. Mesmo que este não é o mesmo que trocar os bits, alternando iria funcionar bem para os meus propósitos.

Foi útil?

Solução

Tente:

x ^= 0x14;

que alterna os dois bits. É um pouco mais claro em questão como você primeiro swap menção e, em seguida, dar um exemplo de alternância. De qualquer forma, para trocar os bits:

x = precomputed_lookup [x];

onde precomputed_lookup é uma matriz de 256 bytes, poderia ser a maneira mais rápida, isso depende da velocidade da memória em relação à velocidade do processador. Caso contrário, é:

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

EDIT:. Alguns mais informações sobre alternar pedaços

Quando você xor (^) dois valores inteiros juntos, o XOR é executada no nível de bit, como este:

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

para que bit 0 do primeiro valor é xor'ed com bit 0 do segundo valor, o bit 1 com o bit 1 e assim por diante. A operação xor não afeta os outros bits do valor. Com efeito, é um xor bit paralelo em muitos bits.

Olhando para a tabela verdade para XOR, você vai ver que xor'ing um pouco com o valor '1' efetivamente alterna o bit.

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

Assim, para alternar os bits 1 e 3, escrever um número binário com um onde deseja que o bit de alternância e um zero onde você quer deixar o valor inalterado:

00001010

convertido ao hex: 0x0a. Você pode alternar o maior número de bits como você deseja:

0x39 = 00111001

vai activar o bit 0, 3, 4 e 5

Outras dicas

Você não pode "swap" dois bits (isto é, os bits de mudar de lugar, não o valor) em uma única instrução usando bit-mexer.

A abordagem ideal se você quiser realmente trocá-los é provavelmente uma tabela de pesquisa. Isso vale para muitas transformações 'estranhas'.

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

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

O método a seguir não é uma única instrução C, é apenas um outro método pouco mexer. O método foi simplificado de Permuta bits individuais com XOR .

Tal como referido na resposta de Roddy , uma tabela de pesquisa seria melhor. Eu apenas sugerir isso no caso de você não quiser usar um. Isto vai realmente trocar bits também, não apenas de alternância (ou seja, o que está no bit 2 será em 4 e vice-versa).

  • b:? O seu valor original - ??? 1 0 ?? por exemplo
  • x: apenas um temp
  • r: o resultado

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

explicação rápida: obter os dois bits que você quer olhar e XOR, guarde o valor para x. Ao mudar esse valor de volta para os bits 2 e 4 (e ouestáespecificando juntos), obtém uma máscara que, quando XORed volta com b vai trocar seus dois bits originais. A tabela abaixo mostra todos os casos possíveis.

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

Eu não totalmente testar isso, mas para os poucos casos que eu tentei rapidamente parecia trabalho.

Isto pode não ser otimizado, mas deve 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;
}

A função abaixo pedaços vai trocar 2 e 4. Você pode usar isso para precompute uma tabela de pesquisa, se necessário (para que a troca torna-se uma única operação):

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

Eu escrevi cada operação em uma linha separada para torná-lo mais claro.

Digamos que seu valor é x ou seja, x = ??? 1? 0 ??

Os dois bits pode ser alternada por esta operação:

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 é o inteiro que você quer ser trocados, a e b são as posições (indicadores) dos bits que você quer ser trocados, a contar do bit menos significativo e começando do zero.

Usando o seu exemplo (n = ???1?0??), você chamar a função da seguinte forma:

swap_bits(n, 2, 4);

Justificação : você só precisa trocar os bits se eles são diferentes (por isso r != s). Neste caso, um deles é um eo outro é 0. Depois disso, basta notar que você quer fazer exatamente um conjunto de bits operação e um mordeu operação de limpeza.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top