Recherche…


Remarques

Les opérations de décalage de bits ne sont pas portables pour toutes les architectures de processeur, différents processeurs peuvent avoir des largeurs de bits différentes. En d'autres termes, si vous écriviez

int a = ~0;
int b = a << 1;

Cette valeur serait différente sur une machine 64 bits par rapport à une machine 32 bits, ou entre un processeur x86 et un processeur PIC.

Endian-ness n'a pas besoin d'être pris en compte pour les opérations sur les bits elles-mêmes, c'est-à-dire que le décalage vers la droite ( >> ) décale les bits vers le bit le moins significatif et qu'un XOR exécute un bit exclusif ou sur les bits. Endian-ness n'a besoin d'être pris en compte que par les données elles-mêmes, c'est-à-dire que si l'endian-ness est une préoccupation pour votre application, il s'agit d'une préoccupation indépendamment des opérations sur les bits.

& - bitwise AND

int a = 6;     // 0110b  (0x06)
int b = 10;    // 1010b  (0x0A)
int c = a & b; // 0010b  (0x02)

std::cout << "a = " << a << ", b = " << b << ", c = " << c << std::endl;

Sortie

a = 6, b = 10, c = 2

Pourquoi

Un peu sage AND fonctionne sur le niveau du bit et utilise la table de vérité booléenne suivante:

TRUE  AND TRUE  = TRUE
TRUE  AND FALSE = FALSE
FALSE AND FALSE = FALSE

Lorsque la valeur binaire pour a ( 0110 ) et la valeur binaire pour b ( 1010 ) sont AND ensemble, nous obtenons la valeur binaire de 0010 :

int a = 0 1 1 0
int b = 1 0 1 0 &
        ---------
int c = 0 0 1 0

Le bit sages ET ne modifie pas la valeur des valeurs d'origine, à moins que cela ne soit spécifiquement attribué à l'utilisation de l'opérateur de mappage par bits &= :

int a = 5;  // 0101b  (0x05)
a &= 10;    // a = 0101b & 1010b

| - bit à bit OU

int a = 5;     // 0101b  (0x05)
int b = 12;    // 1100b  (0x0C)
int c = a | b; // 1101b  (0x0D)

std::cout << "a = " << a << ", b = " << b << ", c = " << c << std::endl;

Sortie

a = 5, b = 12, c = 13

Pourquoi

Un peu sage OR fonctionne sur le niveau du bit et utilise la table de vérité booléenne suivante:

true OR true = true
true OR false = true
false OR false = false

Lorsque la valeur binaire pour a ( 0101 ) et la valeur binaire pour b ( 1100 ) sont OR ensemble, nous obtenons la valeur binaire de 1101 :

int a = 0 1 0 1
int b = 1 1 0 0 |
        ---------
int c = 1 1 0 1

Le bit sages OU ne modifie pas la valeur des valeurs d'origine à moins que ce soit spécifiquement affecté à l'aide de l'opérateur composé d'affectation par bit |= :

int a = 5;  // 0101b  (0x05)
a |= 12;    // a = 0101b | 1101b

^ - bit à bit XOR (OU exclusif)

int a = 5;     // 0101b  (0x05)
int b = 9;     // 1001b  (0x09)
int c = a ^ b; // 1100b  (0x0C)

std::cout << "a = " << a << ", b = " << b << ", c = " << c << std::endl;

Sortie

a = 5, b = 9, c = 12

Pourquoi

Un peu XOR (exclusif ou) opère au niveau du bit et utilise la table de vérité booléenne suivante:

true OR true = false
true OR false = true
false OR false = false

Notez qu'avec une opération XOR true OR true = false où avec des opérations true AND/OR true = true , d'où la nature exclusive de l'opération XOR.

En utilisant ceci, lorsque la valeur binaire pour a ( 0101 ) et la valeur binaire pour b ( 1001 ) sont XOR ensemble, nous obtenons la valeur binaire de 1100 :

int a = 0 1 0 1
int b = 1 0 0 1 ^
        ---------
int c = 1 1 0 0

Le bit XOR ne modifie pas la valeur des valeurs d'origine, à moins que cela ne soit spécifiquement attribué à l'utilisation de l'opérateur composé d'affectation par bit ^= :

int a = 5;  // 0101b  (0x05)
a ^= 9;    // a = 0101b ^ 1001b

Le bit XOR peut être utilisé de nombreuses manières et est souvent utilisé dans les opérations de masque binaire pour le chiffrement et la compression.

Remarque: L’exemple suivant est souvent présenté comme un exemple d’astuce. Mais ne devrait pas être utilisé dans le code de production (il existe de meilleures méthodes std::swap() pour obtenir le même résultat).

Vous pouvez également utiliser une opération XOR pour échanger deux variables sans temporaire:

int a = 42;
int b = 64;

// XOR swap
a ^= b;
b ^= a;
a ^= b;

std::cout << "a = " << a << ", b = " << b << "\n";

Pour produire cela, vous devez ajouter une vérification pour vous assurer qu'il peut être utilisé.

void doXORSwap(int& a, int& b)
{
    // Need to add a check to make sure you are not swapping the same
    // variable with itself. Otherwise it will zero the value.
    if (&a != &b)
    {
        // XOR swap
        a ^= b;
        b ^= a;
        a ^= b;
    }
}

Donc, bien que cela ressemble à une astuce en vase clos, ce n'est pas utile en code réel. xor n'est pas une opération logique de base, mais une combinaison d'autres opérations: a ^ c = ~ (a & c) & (a | c)

également en 2015+ les variables de compilateurs peuvent être assignées comme binaires:

int cn=0b0111;

~ - bitwise NOT (complément unaire)

unsigned char a = 234;  // 1110 1010b  (0xEA)
unsigned char b = ~a;   // 0001 0101b  (0x15)

std::cout << "a = " << static_cast<int>(a) <<
             ", b = " << static_cast<int>(b) << std::endl;

Sortie

a = 234, b = 21

Pourquoi

Un peu sage NOT (complément unaire) fonctionne sur le niveau du bit et chaque bit est réfléchi. Si c'est un 1 , il est changé en 0 , si c'est un 0 , il est changé en 1 . Le bit not not NOT a le même effet que XOR sur une valeur par rapport à la valeur max pour un type spécifique:

unsigned char a = 234;  // 1110 1010b  (0xEA)
unsigned char b = ~a;   // 0001 0101b  (0x15)
unsigned char c = a ^ ~0;

Le bit not NON peut aussi être un moyen pratique de vérifier la valeur maximale d'un type entier spécifique:

unsigned int i = ~0;
unsigned char c = ~0;

std::cout << "max uint = " << i << std::endl <<
             "max uchar = " << static_cast<short>(c) << std::endl;

Le bit not not NOT ne change pas la valeur de la valeur d'origine et n'a pas d'opérateur d'affectation composé, vous ne pouvez donc pas faire a ~= 10 par exemple.

Le bit not not NOT ( ~ ) ne doit pas être confondu avec le NOT logique ( ! ); où un peu sage ne retournera pas chaque bit, un NOT logique utilisera la valeur entière pour effectuer son opération, en d'autres termes (!1) != (~1)

<< - décalage gauche

int a = 1;      // 0001b
int b = a << 1; // 0010b

std::cout << "a = " << a << ", b = " << b << std::endl;

Sortie

a = 1, b = 2

Pourquoi

Le décalage gauche sage décalera les bits de la valeur de gauche ( a ) le nombre spécifié à droite ( 1 ), remplissant essentiellement les bits les moins significatifs avec les 0, déplaçant ainsi la valeur de 5 ( 0000 0101 binaire) à gauche 4 fois (par exemple 5 << 4 ) donneront la valeur de 80 (binaire 0101 0000 ). Vous remarquerez peut-être que le fait de déplacer une valeur vers la gauche 1 fois est également identique à la multiplication de la valeur 2, par exemple:

int a = 7;
while (a < 200) {
    std::cout << "a = " << a << std::endl;
    a <<= 1;
}

a = 7;
while (a < 200) {
    std::cout << "a = " << a << std::endl;
    a *= 2;
}

Mais il convient de noter que l’opération de décalage vers la gauche décale tous les bits vers la gauche, y compris le bit de signe, par exemple:

int a = 2147483647; // 0111 1111 1111 1111 1111 1111 1111 1111
int b = a << 1;     // 1111 1111 1111 1111 1111 1111 1111 1110

std::cout << "a = " << a << ", b = " << b << std::endl;

Sortie possible: a = 2147483647, b = -2

Bien que certains compilateurs donneront des résultats qui semblent attendus, il convient de noter que si vous laissez un décalage sur un numéro signé pour que le bit de signe soit affecté, le résultat est indéfini . Il est également indéfini si le nombre de bits que vous souhaitez décaler est un nombre négatif ou est supérieur au nombre de bits que le type à gauche peut contenir, exemple:

int a = 1;
int b = a << -1;  // undefined behavior
char c = a << 20; // undefined behavior

Le décalage gauche au niveau du bit ne modifie pas la valeur des valeurs d’origine, sauf si l’opérateur spécifique d’attribution de bits <<= :

int a = 5;  // 0101b
a <<= 1;    // a = a << 1;

>> - décalage vers la droite

int a = 2;      // 0010b
int b = a >> 1; // 0001b

std::cout << "a = " << a << ", b = " << b << std::endl;

Sortie

a = 2, b = 1

Pourquoi

Le décalage vers la droite permet de décaler les bits de la valeur de gauche ( a ) du nombre spécifié à droite ( 1 ); il convient de noter que si l'opération d'un décalage à droite est standard, ce qui arrive aux bits d'un décalage à droite sur un nombre négatif signé est défini par l'implémentation et ne peut donc pas être garanti portable, par exemple:

int a = -2;    
int b = a >> 1; // the value of b will be depend on the compiler

Il est également indéfini si le nombre de bits que vous souhaitez décaler est un nombre négatif, par exemple:

int a = 1;
int b = a >> -1;  // undefined behavior

Le décalage vers la droite au niveau du bit ne modifie pas la valeur des valeurs d’origine, sauf si elles sont spécifiquement associées à l’utilisation de l’opérateur composé d’affectation par bit >>= :

int a = 2;  // 0010b
a >>= 1;    // a = a >> 1;


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow