Je suis assez nouveau dans la programmation en 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 ? Des exemples seraient les bienvenus.
Réponses
Trop de publicités?Un masque définit les bits que vous souhaitez conserver et ceux que vous souhaitez effacer.
Le masquage est l'action d'appliquer un masque à une valeur. Ceci est accompli en faisant :
- L'association ET par bit afin d'extraire un sous-ensemble de bits dans la valeur.
- L'opération OU par bit afin de définir un sous-ensemble de bits dans la valeur.
- XOR par bit afin de faire basculer un sous-ensemble de bits dans la valeur.
Vous trouverez ci-dessous 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). Nous avons donc extrait les 4 bits inférieurs. Le résultat est le suivant :
Mask: 00001111b
Value: 01010101b
Result: 00000101b
Le masquage est mis en œuvre en utilisant AND, donc en C on obtient :
uint8_t stuff(...) {
uint8_t mask = 0x0f; // 00001111b
uint8_t value = 0x55; // 01010101b
return mask & value;
}
Voici un cas d'utilisation assez courant : Extraire des octets individuels d'un mot plus grand. Nous définissons les bits de poids fort du mot comme le premier octet. Nous utilisons deux opérateurs pour cela, &
y >>
(à droite). C'est ainsi que nous pouvons extraire les quatre octets d'un entier de 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
...
}
Remarquez que vous pouvez inverser 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 vous devez maintenant utiliser un masque différent :
uint32_t byte3 = (value & 0xff00) >> 8;
Masquage signifie conserver/modifier/supprimer une partie souhaitée de l'information. Voyons une opération de masquage d'image ; par exemple, cette opération de masquage supprime tout ce qui n'est pas de la peau
Nous faisons ET dans cet exemple. Il existe également d'autres opérateurs de masquage - OU , XOR .
Masquage de bits signifie imposer un masque sur les bits. Voici un masquage de bits avec ET -
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]
Donc, seuls les 4 bits du milieu (car ces bits sont 1
dans 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 inversés ( 1
est devenu 0
, 0
est devenu 1
).
Donc, en utilisant le masque de bit, nous pouvons accéder aux bits individuels [ exemples ]. Parfois, cette technique peut également être utilisée pour améliorer les performances. Prenons l'exemple suivant.
bool isOdd(int i) {
return i%2;
}
Cette fonction indique si un nombre entier est pair ou impair. Nous pouvons obtenir le même résultat avec plus d'efficacité en utilisant la fonction bit-mask-
bool isOdd(int i) {
return i&1;
}
Explication succincte : Si le bit le moins significatif d'un nombre binaire est 1
alors elle est impaire ; pour 0
il sera égal. Donc, en faisant ET con 1
nous supprimons tous les autres bits sauf le 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]