## Opérateurs sur les bits

Les opérateurs sur les bits permettent d'évaluer et de manipuler des bits spécifiques dans un entier.

Les opérateurs sur les bits
Exemple | Nom | Résultat
--- | --- | ---
`$a & $b` | And (Et) | Les bits positionnés à 1 dans $a ET dans $b sont positionnés à 1.
`$a | $b` | Or (Ou) | Les bits positionnés à 1 dans $a OU $b sont positionnés à 1.
`$a ^ $b` | Xor (ou exclusif) | Les bits positionnés à 1 dans $a OU dans $b mais pas dans les deux sont positionnés à 1.
`~ $a` | Not (Non) | Les bits qui sont positionnés à 1 dans $a sont positionnés à 0, et vice-versa.
`$a << $b` | Décalage à gauche | Décale les bits de $a, $b fois sur la gauche (chaque décalage équivaut à une multiplication par 2).
`$a >> $b` | Décalage à droite | Décale les bits de $a, $b fois sur la droite (chaque décalage équivaut à une division par 2).

Le décalage de bits en PHP est arithmétique. Les bits qui sont décalés hors de l'entier sont perdus. Les décalages à gauche font apparaître des zéros à droite, tandis que le bit de signe est décalé à gauche, ce qui signifie que le signe de l'entier n'est pas préservé. Les décalages à droite décalent aussi le bit de signe sur la droite, ce qui signifie que le signe est préservé.

Utiliser des parenthèses pour s'assurer que la précédence voulue est bien appliquée. Par exemple, `$a & $b == true` applique d'abord l'égalité, et ensuite le ET logique, alors que `($a & $b) == true` applique d'abord le ET logique, puis l'égalité.

Si les deux opérandes pour les opérateurs `&`, `|` et `^` sont des chaînes de caractères, alors l'opération sera réalisée sur les valeurs ASCII des caractères et le résultat sera une chaîne de caractères. Dans tous les autres cas, les deux opérandes seront converties en entier et le résultat sera un entier.

Si l'opérande pour l'opérateur `~` est une chaîne de caractères, l'opération sera effectuée sur les caractères ASCII composant la chaîne et le résultat sera une chaîne de caractères. Sinon l'opérande et le résultat seront traités comme des entiers.

Les opérandes et le résultat des opérateurs `<<` et `>>` sont traités comme des entiers.

Le rapport d'erreur de PHP utilise des champs de bits, qui sont une illustration de l'extinction des bits. Pour afficher les erreurs, sauf les notices, les instructions du php.ini sont : `E_ALL & ~E_NOTICE`

         Cela se comprend en comparant avec E_ALL :
         00000000000000000111011111111111
         Puis en prenant la valeur de E_NOTICE...
         00000000000000000000000000001000
         ... et en l'inversant via ~:
         11111111111111111111111111110111
         Finalement, on utilise le ET logique (&) pour lire les bits activés
         dans les deux valeurs :
         00000000000000000111011111110111

Un autre moyen d'arriver à ce résultat est d'utiliser le OU exclusif (`^`), qui cherche les bits qui ne sont activés que dans l'une ou l'autre des valeurs, exclusivement : `E_ALL ^ E_NOTICE`

error_reporting peut aussi être utilisé pour illustrer l'activation de bits. Pour afficher uniquement les erreurs et les erreurs recouvrables, on utilise : `E_ERROR | E_RECOVERABLE_ERROR`

         Cette approche combine E_ERROR
         00000000000000000000000000000001
         et E_RECOVERABLE_ERROR
         00000000000000000001000000000000
         Avec l'opérateur OR (|) pour s'assurer que
         les bits sont activés dans l'une ou l'autre valeur :
         00000000000000000001000000000001

Exemple #1 Opérations sur les bits et les entiers

    <?php
    /*
     * Ignorez cette partie,
     * c'est juste du formatage pour clarifier les résultats
     */

    $format = '(%1$2d = %1$04b) = (%2$2d = %2$04b)'
            . ' %3$s (%4$2d = %4$04b)' . "\n";

    echo <<<EOH
     ---------     ---------  -- ---------
     résultat       valeur        test
     ---------     ---------  -- ---------
    EOH;

    /*
     * Voici les exemples
     */

    $values = array(0, 1, 2, 4, 8);
    $test = 1 + 4;

    echo "\n Bitwise AND \n";
    foreach ($values as $value) {
        $result = $value & $test;
        printf($format, $result, $value, '&', $test);
    }

    echo "\n Bitwise Inclusive OR \n";
    foreach ($values as $value) {
        $result = $value | $test;
        printf($format, $result, $value, '|', $test);
    }

    echo "\n Bitwise Exclusive OR (XOR) \n";
    foreach ($values as $value) {
        $result = $value ^ $test;
        printf($format, $result, $value, '^', $test);
    }
    ?>

L'exemple ci-dessus va afficher :

     ---------     ---------  -- ---------
     résultat       valeur        test
     ---------     ---------  -- ---------
     Bitwise AND
    ( 0 = 0000) = ( 0 = 0000) & ( 5 = 0101)
    ( 1 = 0001) = ( 1 = 0001) & ( 5 = 0101)
    ( 0 = 0000) = ( 2 = 0010) & ( 5 = 0101)
    ( 4 = 0100) = ( 4 = 0100) & ( 5 = 0101)
    ( 0 = 0000) = ( 8 = 1000) & ( 5 = 0101)

     Bitwise Inclusive OR
    ( 5 = 0101) = ( 0 = 0000) | ( 5 = 0101)
    ( 5 = 0101) = ( 1 = 0001) | ( 5 = 0101)
    ( 7 = 0111) = ( 2 = 0010) | ( 5 = 0101)
    ( 5 = 0101) = ( 4 = 0100) | ( 5 = 0101)
    (13 = 1101) = ( 8 = 1000) | ( 5 = 0101)

     Bitwise Exclusive OR (XOR)
    ( 5 = 0101) = ( 0 = 0000) ^ ( 5 = 0101)
    ( 4 = 0100) = ( 1 = 0001) ^ ( 5 = 0101)
    ( 7 = 0111) = ( 2 = 0010) ^ ( 5 = 0101)
    ( 1 = 0001) = ( 4 = 0100) ^ ( 5 = 0101)
    (13 = 1101) = ( 8 = 1000) ^ ( 5 = 0101)

Exemple #2 Opération sur les bits et les chaînes

    <?php
    echo 12 ^ 9, PHP_EOL; // Affiche '5'

    echo "12" ^ "9", PHP_EOL; // Affiche le caractère d'effacement (ascii 8)
                     // ('1' (ascii 49)) ^ ('9' (ascii 57)) = #8

    echo "hallo" ^ "hello", PHP_EOL; // Affiche les valeurs ASCII #0 #4 #0 #0 #0
                            // 'a' ^ 'e' = #4

    echo 2 ^ "3", PHP_EOL; // Affiche 1
                  // 2 ^ ((int) "3") == 1

    echo "2" ^ 3, PHP_EOL; // Affiche 1
                  // ((int) "2") ^ 3 == 1
    ?>

Exemple #3 Décalage de bits sur les entiers

    <?php
    /*
     * Voici quelques exemples
     */

    echo "\n--- Décalages à droite sur des entiers positifs ---\n";

    $val = 4;
    $places = 1;
    $res = $val >> $places;
    p($res, $val, '>>', $places, 'copie du bit de signe maintenant à gauche');

    $val = 4;
    $places = 2;
    $res = $val >> $places;
    p($res, $val, '>>', $places);

    $val = 4;
    $places = 3;
    $res = $val >> $places;
    p($res, $val, '>>', $places, 'des bits sont sortis par la droite');

    $val = 4;
    $places = 4;
    $res = $val >> $places;
    p($res, $val, '>>', $places, 'même résultat que ci-dessus : pas de décalage au-delà de 0');

    echo "\n--- Décalages à droite sur des entiers négatifs ---\n";

    $val = -4;
    $places = 1;
    $res = $val >> $places;
    p($res, $val, '>>', $places, 'copie du bit de signe maintenant à gauche');

    $val = -4;
    $places = 2;
    $res = $val >> $places;
    p($res, $val, '>>', $places, 'des bits sont sortis par la droite');

    $val = -4;
    $places = 3;
    $res = $val >> $places;
    p($res, $val, '>>', $places, 'même résultat que ci-dessus : pas de décalage au-delà de -1');

    echo "\n--- Décalages à gauche sur des entiers positifs ---\n";

    $val = 4;
    $places = 1;
    $res = $val << $places;
    p($res, $val, '<<', $places, 'complément de zéros à droite');

    $val = 4;
    $places = (PHP_INT_SIZE * 8) - 4;
    $res = $val << $places;
    p($res, $val, '<<', $places);

    $val = 4;
    $places = (PHP_INT_SIZE * 8) - 3;
    $res = $val << $places;
    p($res, $val, '<<', $places, 'le bit de signe est sorti');

    $val = 4;
    $places = (PHP_INT_SIZE * 8) - 2;
    $res = $val << $places;
    p($res, $val, '<<', $places, 'des bits sont sortis à gauche');

    echo "\n--- Décalages à gauche sur des entiers négatifs ---\n";

    $val = -4;
    $places = 1;
    $res = $val << $places;
    p($res, $val, '<<', $places, 'complément de zéros à droite');

    $val = -4;
    $places = (PHP_INT_SIZE * 8) - 3;
    $res = $val << $places;
    p($res, $val, '<<', $places);

    $val = -4;
    $places = (PHP_INT_SIZE * 8) - 2;
    $res = $val << $places;
    p($res, $val, '<<', $places, 'des bits sont sortis à gauche, y compris le bit de signe');

    /*
     * Ignorez cette section
     * Elle contient du code pour le formatage de cet exemple
     */

    function p($res, $val, $op, $places, $note = '') {
        $format = '%0' . (PHP_INT_SIZE * 8) . "b\n";

        printf("Expression : %d = %d %s %d\n", $res, $val, $op, $places);

        echo " Décimal :\n";
        printf("  val=%d\n", $val);
        printf("  res=%d\n", $res);

        echo " Binaire :\n";
        printf('  val=' . $format, $val);
        printf('  res=' . $format, $res);

        if ($note) {
            echo " Note : $note\n";
        }

        echo "\n\n";
    }
    ?>

Résultat de l'exemple ci-dessus sur une machine 32 bits :

    --- Décalages à droite sur des entiers positifs ---
    Expression : 2 = 4 >> 1
     Décimal :
      val=4
      res=2
     Binaire :
      val=00000000000000000000000000000100
      res=00000000000000000000000000000010
     Note : copie du bit de signe maintenant à gauche

    Expression : 1 = 4 >> 2
     Décimal :
      val=4
      res=1
     Binaire :
      val=00000000000000000000000000000100
      res=00000000000000000000000000000001

    Expression : 0 = 4 >> 3
     Décimal :
      val=4
      res=0
     Binaire :
      val=00000000000000000000000000000100
      res=00000000000000000000000000000000
     Note : des bits sont sortis par la droite

    Expression : 0 = 4 >> 4
     Décimal :
      val=4
      res=0
     Binaire :
      val=00000000000000000000000000000100
      res=00000000000000000000000000000000
     Note : même résultat que ci-dessus : pas de décalage au-delà de 0

    --- Décalages à droite sur des entiers négatifs ---
    Expression : -2 = -4 >> 1
     Décimal :
      val=-4
      res=-2
     Binaire :
      val=11111111111111111111111111111100
      res=11111111111111111111111111111110
     Note : copie du bit de signe maintenant à gauche

    Expression : -1 = -4 >> 2
     Décimal :
      val=-4
      res=-1
     Binaire :
      val=11111111111111111111111111111100
      res=11111111111111111111111111111111
     Note : des bits sont sortis par la droite

    Expression : -1 = -4 >> 3
     Décimal :
      val=-4
      res=-1
     Binaire :
      val=11111111111111111111111111111100
      res=11111111111111111111111111111111
     Note : même résultat que ci-dessus : pas de décalage au-delà de -1

    --- Décalages à gauche sur des entiers positifs ---
    Expression : 8 = 4 << 1
     Décimal :
      val=4
      res=8
     Binaire :
      val=00000000000000000000000000000100
      res=00000000000000000000000000001000
     Note : complément de zéros à droite

    Expression : 1073741824 = 4 << 28
     Décimal :
      val=4
      res=1073741824
     Binaire :
      val=00000000000000000000000000000100
      res=01000000000000000000000000000000

    Expression : -2147483648 = 4 << 29
     Décimal :
      val=4
      res=-2147483648
     Binaire :
      val=00000000000000000000000000000100
      res=10000000000000000000000000000000
     Note : le bit de signe est sorti

    Expression : 0 = 4 << 30
     Décimal :
      val=4
      res=0
     Binaire :
      val=00000000000000000000000000000100
      res=00000000000000000000000000000000
     Note : des bits sont sortis à gauche

    --- Décalages à gauche sur des entiers négatifs ---
    Expression : -8 = -4 << 1
     Décimal :
      val=-4
      res=-8
     Binaire :
      val=11111111111111111111111111111100
      res=11111111111111111111111111111000
     Note : complément de zéros à droite

    Expression : -2147483648 = -4 << 29
     Décimal :
      val=-4
      res=-2147483648
     Binaire :
      val=11111111111111111111111111111100
      res=10000000000000000000000000000000

    Expression : 0 = -4 << 30
     Décimal :
      val=-4
      res=0
     Binaire :
      val=11111111111111111111111111111100
      res=00000000000000000000000000000000
     Note : des bits sont sortis à gauche, y compris le bit de signe

Résultat de l'exemple ci-dessus sur une machine 64 bits :

    --- Décalages à droite sur des entiers positifs ---
    Expression : 2 = 4 >> 1
     Décimal :
      val=4
      res=2
     Binaire :
      val=0000000000000000000000000000000000000000000000000000000000000100
      res=0000000000000000000000000000000000000000000000000000000000000010
     Note : copie du bit de signe maintenant à gauche

    Expression : 1 = 4 >> 2
     Décimal :
      val=4
      res=1
     Binaire :
      val=0000000000000000000000000000000000000000000000000000000000000100
      res=0000000000000000000000000000000000000000000000000000000000000001

    Expression : 0 = 4 >> 3
     Décimal :
      val=4
      res=0
     Binaire :
      val=0000000000000000000000000000000000000000000000000000000000000100
      res=0000000000000000000000000000000000000000000000000000000000000000
     Note : des bits sont sortis par la droite

    Expression : 0 = 4 >> 4
     Décimal :
      val=4
      res=0
     Binaire :
      val=0000000000000000000000000000000000000000000000000000000000000100
      res=0000000000000000000000000000000000000000000000000000000000000000
     Note : même résultat que ci-dessus : pas de décalage au-delà de 0

    --- Décalages à droite sur des entiers négatifs ---
    Expression : -2 = -4 >> 1
     Décimal :
      val=-4
      res=-2
     Binaire :
      val=1111111111111111111111111111111111111111111111111111111111111100
      res=1111111111111111111111111111111111111111111111111111111111111110
     Note : copie du bit de signe maintenant à gauche

    Expression : -1 = -4 >> 2
     Décimal :
      val=-4
      res=-1
     Binaire :
      val=1111111111111111111111111111111111111111111111111111111111111100
      res=1111111111111111111111111111111111111111111111111111111111111111
     Note : des bits sont sortis par la droite

    Expression : -1 = -4 >> 3
     Décimal :
      val=-4
      res=-1
     Binaire :
      val=1111111111111111111111111111111111111111111111111111111111111100
      res=1111111111111111111111111111111111111111111111111111111111111111
     Note : même résultat que ci-dessus : pas de décalage au-delà de -1

    --- Décalage à gauche sur les entiers positifs ---
    Expression : 8 = 4 << 1
     Décimal :
      val=4
      res=8
     Binaire :
      val=0000000000000000000000000000000000000000000000000000000000000100
      res=0000000000000000000000000000000000000000000000000000000000001000
     Note : complément de zéros à droite

    Expression : 4611686018427387904 = 4 << 60
     Décimal :
      val=4
      res=4611686018427387904
     Binaire :
      val=0000000000000000000000000000000000000000000000000000000000000100
      res=0100000000000000000000000000000000000000000000000000000000000000

    Expression : -9223372036854775808 = 4 << 61
     Décimal :
      val=4
      res=-9223372036854775808
     Binaire :
      val=0000000000000000000000000000000000000000000000000000000000000100
      res=1000000000000000000000000000000000000000000000000000000000000000
     Note : le bit de signe est sorti

    Expression : 0 = 4 << 62
     Décimal :
      val=4
      res=0
     Binaire :
      val=0000000000000000000000000000000000000000000000000000000000000100
      res=0000000000000000000000000000000000000000000000000000000000000000
     Note : des bits sont sortis à gauche

    --- Décalage à gauche sur les entiers négatifs ---
    Expression : -8 = -4 << 1
     Décimal :
      val=-4
      res=-8
     Binaire :
      val=1111111111111111111111111111111111111111111111111111111111111100
      res=1111111111111111111111111111111111111111111111111111111111111000
     Note : complément de zéros à droite

    Expression : -9223372036854775808 = -4 << 61
     Décimal :
      val=-4
      res=-9223372036854775808
     Binaire :
      val=1111111111111111111111111111111111111111111111111111111111111100
      res=1000000000000000000000000000000000000000000000000000000000000000

    Expression : 0 = -4 << 62
     Décimal :
      val=-4
      res=0
     Binaire :
      val=1111111111111111111111111111111111111111111111111111111111111100
      res=0000000000000000000000000000000000000000000000000000000000000000
     Note : des bits sont sortis à gauche, y compris le bit de signe

Avertissement

Utiliser les fonctions de l'extension gmp pour les manipulations sur les bits, lorsque les entiers dépassent `PHP_INT_MAX`.

### Voir aussi

- pack()
- unpack()
- gmp_and()
- gmp_or()
- gmp_xor()
- gmp_testbit()
- gmp_clrbit()

`↑` and `↓` to navigate • `Enter` to select • `Esc` to close • `/` to open