Qu'est-ce que le masquage de bits?

205

Je suis assez nouveau dans la programmation C et j'ai rencontré le masquage de bits. Quelqu'un peut-il m'expliquer le concept général et la fonction du masquage de bits? Les exemples sont très appréciés.

Monsieur Z
la source
1
Comprenez-vous les opérateurs binaires tels que & | ^ etc et la logique booléenne en général? Toute explication des opérations de masque en exigera.
Paul R
1
Oui, j'ai une compréhension des opérateurs
binaires
2
Je sais que les liens ne doivent pas être publiés, mais l'explication de wikipedia est excellente: en.wikipedia.org/wiki/Mask_(computing)
pevik
2
@pevik c'est ok pour publier un lien mais avec une description afin que si le lien meurt un jour, le message soit toujours en mesure de remplir son objectif de réponse. également le lien ne doit pas être à des fins purement promotionnelles.
Dexter

Réponses:

255

Un masque définit les bits que vous souhaitez conserver et les bits que vous souhaitez effacer.

Le masquage est l'acte d'appliquer un masque à une valeur. Ceci est accompli en faisant:

  • AND au niveau du bit pour extraire un sous-ensemble des bits de la valeur
  • OR au niveau du bit afin de définir un sous-ensemble des bits dans la valeur
  • XORing au niveau du bit afin de basculer un sous-ensemble de bits dans la valeur

Voici un exemple d'extraction d'un sous-ensemble de bits dans la valeur:

Mask:   00001111b
Value:  01010101b

Appliquer le masque à la valeur signifie que nous voulons effacer les 4 premiers bits (supérieurs) et conserver les 4 derniers bits (inférieurs). Ainsi, nous avons extrait les 4 bits inférieurs. Le résultat est:

Mask:   00001111b
Value:  01010101b
Result: 00000101b

Le masquage est implémenté en utilisant AND, donc en C nous obtenons:

uint8_t stuff(...) {
  uint8_t mask = 0x0f;   // 00001111b
  uint8_t value = 0x55;  // 01010101b
  return mask & value;
}

Voici un cas d'utilisation assez courant: l'extraction d'octets individuels d'un mot plus grand. Nous définissons les bits de poids fort dans le mot comme le premier octet. Nous utilisons deux opérateurs pour cela &, et >>(décalage vers la droite). Voici comment nous pouvons extraire les quatre octets d'un entier 32 bits:

void more_stuff(uint32_t value) {             // Example value: 0x01020304
    uint32_t byte1 = (value >> 24);           // 0x01020304 >> 24 is 0x01 so
                                              // no masking is necessary
    uint32_t byte2 = (value >> 16) & 0xff;    // 0x01020304 >> 16 is 0x0102 so
                                              // we must mask to get 0x02
    uint32_t byte3 = (value >> 8)  & 0xff;    // 0x01020304 >> 8 is 0x010203 so
                                              // we must mask to get 0x03
    uint32_t byte4 = value & 0xff;            // here we only mask, no shifting
                                              // is necessary
    ...
}

Notez que vous pouvez changer l'ordre des opérateurs ci-dessus, vous pouvez d'abord faire le masque, puis le décalage. Les résultats sont les mêmes, mais maintenant, vous devrez utiliser un masque différent:

uint32_t byte3 = (value & 0xff00) >> 8;
user239558
la source
6
Bonne réponse, mais le masquage peut également être appliqué pour définir ou basculer des bits spécifiques avec des opérations OU ou XOR et un masque approprié.
Paul R
@ user239558 merci pour l'exemple et la syntaxe appropriée. @ Paul R. Pourrais-je simplement dire masque ET valeur dans l'exemple fourni par user239558
Mr.Z
@ Mr.Z: en C, C ++ et les langages associés, vous utiliseriez l' opérateur binaire AND , qui s'écrit &.
Paul R
@ Mr.Z Par exemple: un octet clair d'un uint32_t en masquant le contenu loin: #define MASK 0x000000FF .... my_uint32_t &= ~MASK.
Lundin
1
Une partie de la confusion survient peut-être à cause du mauvais choix du nom et des verbes pour décrire ce qui se passe réellement. Par exemple, un mot comme "Bitselector" ou "TargetBits" ne semble-t-il pas plus approprié pour décrire l'objet au lieu d'utiliser le mot "Bitmask"? De même, pour décrire les opérations de manipulation de bits, l'utilisation d'un mot tel que "BitManipulate" semble plus approprié que le mot "Masking" car ce dernier n'a de sens que pour les opérations AND mais pas pour XORING (basculer les bits) ou OR (définir les bits) qui sont plutôt des manipulations ou des transformations de bits mais pas des opérations de masquage.
nurabha
91

Masquer signifie conserver / modifier / supprimer une partie souhaitée de l'information. Permet de voir une opération de masquage d'image; comme- cette opération de masquage supprime tout ce qui n'est pas de la peau-

entrez la description de l'image ici

Nous faisons l' opération AND dans cet exemple. Il existe également d'autres opérateurs de masquage - OR , XOR .


Bit-Masking signifie imposer un masque sur les bits. Voici un peu de masquage avec AND -

     1 1 1 0 1 1 0 1   [input]
(&)  0 0 1 1 1 1 0 0    [mask]
------------------------------
     0 0 1 0 1 1 0 0  [output]

Ainsi, seuls les 4 bits du milieu (car ces bits sont 1dans ce masque) restent.

Voyons cela avec XOR -

     1 1 1 0 1 1 0 1   [input]
(^)  0 0 1 1 1 1 0 0    [mask]
------------------------------
     1 1 0 1 0 0 0 1  [output]

Maintenant, les 4 bits du milieu sont retournés ( 1devenus 0, sont 0devenus 1).


Ainsi, en utilisant le masque de bits, nous pouvons accéder à des bits individuels [ exemples ]. Parfois, cette technique peut également être utilisée pour améliorer les performances. Prenez ceci par exemple-

bool isOdd(int i) {
    return i%2;
}

Cette fonction indique si un entier est pair / impair. Nous pouvons obtenir le même résultat avec plus d'efficacité en utilisant le masque de bits-

bool isOdd(int i) {
    return i&1;
}

Explication courte : Si le bit le moins significatif d'un nombre binaire est 1alors il est impair; car 0ce sera égal. Donc, en faisant ET avec, 1nous supprimons tous les autres bits à l'exception du bit le moins significatif, c'est-à-dire:

     55  ->  0 0 1 1 0 1 1 1   [input]
(&)   1  ->  0 0 0 0 0 0 0 1    [mask]
---------------------------------------
      1  <-  0 0 0 0 0 0 0 1  [output]
Minhas Kamal
la source
1
Aussi, pour convertir un entier en un nombre impair. s'il s'agit d'un nombre pair: i = i | 1. Cela est pratique lorsque nous essayons de générer une séquence comme 1, 3, 5, ..., 2, 4, 6, ...
Harshit Sharma
Vous pouvez également utiliser l'opération suivante pour trouver le nombre avec uniquement le bit le moins significatif d'un entier: lsb = i & -i
Harshit Sharma