web-dev-qa-db-fra.com

Comment utiliser le bitmask?

Comment puis-je l'utiliser en C++? quand est-il utile d'utiliser?
S'il vous plaît, donnez-moi un exemple de problème d'utilisation de bitmask et de son fonctionnement. Merci!

52
Animea Animea

Le masquage des bits est "utile" à utiliser lorsque vous souhaitez stocker (puis extraire) différentes données dans une seule valeur.

Un exemple d’application que j’ai utilisé auparavant est l’imagination que vous stockiez des valeurs RVB de couleur dans une valeur 16 bits. Donc, quelque chose qui ressemble à ceci:

RRRR RGGG GGGB BBBB

Vous pouvez ensuite utiliser le masquage de bits pour récupérer les composants de couleur comme suit:

  const unsigned short redMask   = 0xF800;
  const unsigned short greenMask = 0x07E0;
  const unsigned short blueMask  = 0x001F;

  unsigned short lightGray = 0x7BEF;

  unsigned short redComponent   = (lightGray & redMask) >> 11;
  unsigned short greenComponent = (lightGray & greenMask) >> 5;
  unsigned short blueComponent =  (lightGray & blueMask);
31
Dutts

En bref, bitmask permet de manipuler la position de plusieurs valeurs. Il y a un bon exemple ici;

Les bitflags sont une méthode de stockage de plusieurs valeurs, qui ne s'excluent pas mutuellement, dans une variable. Vous les avez probablement déjà vu auparavant. Chaque drapeau est une position de bit qui peut être activée ou désactivée. Vous avez ensuite un tas de bitmasks # définis pour chaque position de bit afin de pouvoir les manipuler facilement:

    #define LOG_ERRORS            1  // 2^0, bit 0
    #define LOG_WARNINGS          2  // 2^1, bit 1
    #define LOG_NOTICES           4  // 2^2, bit 2
    #define LOG_INCOMING          8  // 2^3, bit 3
    #define LOG_OUTGOING         16  // 2^4, bit 4
    #define LOG_LOOPBACK         32  // and so on...

// Only 6 flags/bits used, so a char is fine
unsigned char flags;

// initialising the flags
// note that assigning a value will clobber any other flags, so you
// should generally only use the = operator when initialising vars.
flags = LOG_ERRORS;
// sets to 1 i.e. bit 0

//initialising to multiple values with OR (|)
flags = LOG_ERRORS | LOG_WARNINGS | LOG_INCOMING;
// sets to 1 + 2 + 8 i.e. bits 0, 1 and 3

// setting one flag on, leaving the rest untouched
// OR bitmask with the current value
flags |= LOG_INCOMING;

// testing for a flag
// AND with the bitmask before testing with ==
if ((flags & LOG_WARNINGS) == LOG_WARNINGS)
   ...

// testing for multiple flags
// as above, OR the bitmasks
if ((flags & (LOG_INCOMING | LOG_OUTGOING))
         == (LOG_INCOMING | LOG_OUTGOING))
   ...

// removing a flag, leaving the rest untouched
// AND with the inverse (NOT) of the bitmask
flags &= ~LOG_OUTGOING;

// toggling a flag, leaving the rest untouched
flags ^= LOG_LOOPBACK;



**

AVERTISSEMENT: N'UTILISEZ PAS l'opérateur d'égalité (par exemple, bitflags == bitmask) pour vérifier si un indicateur est défini - cette expression ne sera vraie que si cet indicateur est défini et que tous les autres ne sont pas définis. Pour tester un seul drapeau, vous devez utiliser & et ==:

**

if (flags == LOG_WARNINGS) //DON'T DO THIS
   ...
if ((flags & LOG_WARNINGS) == LOG_WARNINGS) // The right way
   ...
if ((flags & (LOG_INCOMING | LOG_OUTGOING)) // Test for multiple flags set
         == (LOG_INCOMING | LOG_OUTGOING))
   ...

Vous pouvez également rechercher C++ Triks

102
goGud

Disons que j'ai une valeur ARGB 32 bits avec 8 bits par canal. Je souhaite remplacer le composant alpha par une autre valeur alpha, telle que 0x45

unsigned long alpha = 0x45
unsigned long pixel = 0x12345678;
pixel = ((pixel & 0x00FFFFFF) | (alpha << 24));

Le masque met les 8 bits supérieurs à 0, où se trouvait l'ancienne valeur alpha. La valeur alpha est décalée jusqu'aux positions finales des bits qu’elle prendra, puis elle est exprimée en OU dans la valeur de pixel masquée. Le résultat final est 0x45345678 qui est stocké en pixel.

3
Neil Kirk

Les masques de bits sont utilisés lorsque vous souhaitez coder plusieurs couches d'informations dans un même numéro.

Ainsi (en supposant que les autorisations de fichiers soient unix), si vous souhaitez stocker 3 niveaux de restriction d'accès (lecture, écriture, exécution), vous pouvez vérifier chaque niveau en vérifiant le bit correspondant.

rwx
---
110

110 en base 2 se traduit par 6 en base 10.

Ainsi, vous pouvez facilement vérifier si quelqu'un est autorisé à, par exemple, lisez le fichier en indiquant le champ d'autorisation avec l'autorisation demandée.

Pseudocode:

PERM_READ = 4
PERM_WRITE = 2
PERM_EXEC = 1

user_permissions = 6

if (user_permissions & PERM_READ == TRUE) then
  // this will be reached, as 6 & 4 is true
fi

Vous devez comprendre la représentation binaire des nombres et les opérateurs logiques pour comprendre les champs de bits.

3
til_b