Question

Disons que j'ai un octet avec six valeurs inconnues:

???1?0??

et je souhaite échanger les bits 2 et 4 ( sans de changer toutes les valeurs de ?):

???0?1??

Mais comment pourrais-je faire dans une opération en C?

Je suis d'effectuer cette opération des milliers de fois par seconde sur un microcontrôleur si la performance est la priorité absolue.

Il serait bien de « basculer » ces bits. Même si ce n'est pas la même chose que la permutation des bits, fonctionnerait très bien basculement pour mes besoins.

Était-ce utile?

La solution

Essayez:

x ^= 0x14;

qui permet de basculer les deux bits. Il est un peu en question peu claire que vous premier swap de mention, puis donner un exemple à bascule. Quoi qu'il en soit, pour échanger les bits:

x = precomputed_lookup [x];

où precomputed_lookup est un tableau de 256 octets, peut être le moyen le plus rapide, cela dépend de la vitesse de la mémoire par rapport à la vitesse du processeur. Dans le cas contraire, il est:

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

EDIT:. Un peu plus d'informations sur les bits basculer

Lorsque vous XOR (^) deux valeurs entières ensemble, le XOR est effectuée au niveau du bit, comme ceci:

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

de telle sorte que le bit 0 de la première valeur est 0 OU Exclusif avec le bit de la seconde valeur, le bit 1 à bit 1 et ainsi de suite. L'opération XOR ne touche pas les autres bits de la valeur. En effet, il est un XOR bit parallèle sur le nombre de bits.

En regardant la table de vérité pour XOR, vous verrez que xor'ing un peu avec la valeur « 1 » permet de basculer efficacement le bit.

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

Alors, pour activer les bits 1 et 3, écrire un nombre binaire avec celui où vous voulez que le bit à bascule et un zéro où vous voulez laisser la valeur inchangée:

00001010

convertir en hexadécimal: 0x0a. Vous pouvez passer autant de bits que vous voulez:

0x39 = 00111001

basculera bits 0, 3, 4 et 5

Autres conseils

Vous ne pouvez pas « swap » deux bits (à savoir les bits changent de place, pas de valeur) dans une instruction unique à l'aide de bits tripoter.

L'approche optimale si vous voulez les échanger vraiment est probablement une table de consultation. Cela est vrai pour de nombreuses transformations « maladroites ».

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

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

La méthode suivante est pas une seule instruction C, il est juste une autre méthode tripoter bits. La méthode a été simplifiée à partir de Permutation bits individuels avec XOR .

Comme indiqué dans la réponse Roddy , une table de consultation serait préférable. Je ne suggère cela dans le cas où vous ne souhaitez pas utiliser un. Ce sera en effet échanger des bits aussi, non seulement basculer (qui est, ce qui est dans le bit 2 sera en 4 et vice-versa).

  • b: votre valeur initiale - ??? 1 0 ?? par exemple
  • x: juste une température
  • r: le résultat

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

Explication rapide: obtenez les deux bits que vous voulez regarder et les XOR, stocker la valeur à x. En déplaçant cette valeur à bits 2 et 4 (et en même temps avec l'opérateur OR) vous obtenez un masque que lorsque XORed arrière avec b va troquer vos deux bits d'origine. Le tableau ci-dessous montre tous les cas possibles.

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

Je ne teste pas complètement, mais pour les quelques cas, je l'ai essayé semblait travailler rapidement.

Cela pourrait ne pas être optimisé, mais il devrait fonctionner:

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 fonction ci-dessous permuter les bits 2 et 4. Vous pouvez l'utiliser pour précalculer une table de consultation, si nécessaire (pour que swapping devienne une seule opération):

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

J'ai écrit chaque opération sur une ligne distincte pour la rendre plus claire.

Supposons que votre valeur est x i.e., x = ??? 1? 0 ??

Les deux bits peuvent être basculés par cette opération:

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 est l'entier que vous voulez être permutés dans, a et b sont les positions (index) des bits que vous voulez être permutés, à compter du peu moins importante et à partir de zéro.

En utilisant votre exemple (n = ???1?0??), vous appelez la fonction comme suit:

swap_bits(n, 2, 4);

Justification : il vous suffit d'échanger les bits si elles sont différentes (c'est pourquoi r != s). Dans ce cas, l'un d'eux est 1 et l'autre est 0. Après cela, juste remarque que vous voulez faire exactement un bit set et un fonctionnement peu claire opération .

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top