## Bit-Operatoren

Bit-Operatoren erlauben es die Prüfung und Manipulation von bestimmten Bits in einem Integer.

Bit-Operatoren
Beispiel | Name | Ergebnis
--- | --- | ---
`$a & $b` | And (Und) | Bits, die in $a und $b gesetzt sind, werden gesetzt.
`$a | $b` | Or (inklusives Oder) | Bits, die in $a oder $b gesetzt sind, werden gesetzt.
`$a ^ $b` | Xor (exklusives Oder) | Bits, die entweder in $a oder $b, jedoch nicht in beiden gesetzt sind, werden gesetzt.
`~ $a` | Not (Nicht) | Bits, die in $a nicht gesetzt sind, werden gesetzt, und umgekehrt.
`$a << $b` | Nach links verschieben | Verschiebung der Bits von $a um $b Stellen nach links (jede Stelle entspricht einer Mulitplikation mit zwei).
`$a >> $b` | Nach rechts verschieben | Verschiebung der Bits von $a um $b Stellen nach rechts (jede Stelle entspricht einer Division durch zwei).

Bit-Verschiebungen in PHP sind arithmetisch. Bits, die an einem der Enden herausgeschoben werden, werden verworfen. Bei Links-Verschiebungen werden von rechts Nullen hereingeschoben, während das Vorzeichenbit links herausgeschoben wird, was bedeutet, dass das Vorzeichen des Operanden nicht erhalten bleibt. Bei Rechts-Verschiebungen werden Kopien des Vorzeichenbits von links hereingeschoben, sodass das Vorzeichen des Operanden erhalten bleibt.

Klammern sind zu verwenden, um die gewünschte Rangfolge sicherzustellen. Beispielsweise wird bei `$a & $b == true` zunächst der Vergleich ausgewertet, und erst dann das Bit-Und, während bei `($a & $b) == true` zunächst das Bit-Und, und erst dann der Vergleich ausgewertet wird.

Sind beide Operanden der `&`, `|` und `^` Operatoren Zeichenketten, dann wird die Operation auf den ASCII-Werten der Zeichen der Zeichenketten durchgeführt, und das Ergebnis ist wiederum eine Zeichenkette. In allen anderen Fällen werden beide Operanden nach Integer umgewandelt und das Ergebnis ist eine Ganzzahl.

Ist der Operand des `~` Operators eine Zeichenkette, dann wird die Operation auf den ASCII-Werten der Zeichen der Zeichenkette durchgeführt, Und das Ergebnis ist wiederum eine Zeichenkette. Andernfalls werden Operand und Ergebnis als Ganzzahl behandelt.

Beide Operanden und das Ergebnis der `<<` und `>>`-Operatoren werden immer als Ganzzahl behandelt.

Die ini-Einstellung error_reporting von PHP verwendet Bitwerte, was die realitätsnahe Demonstration des Ausschaltens einzelner Bits bietet. Um alle Fehler außer Hinweisen anzuzeigen, muss den Anweisungen der php.ini-Datei entsprechend verwendet werden: `E_ALL & ~E_NOTICE`

         Dies funktioniert, indem mit E_ALL begonnen wird:
         00000000000000000111011111111111
         Dann wird der Wert von E_NOTICE genommen...
         00000000000000000000000000001000
         ... und dieser per ~ invertiert:
         11111111111111111111111111110111
         Schließlich wird AND (&) verwendet, um die Bits zu ermitteln, die in
         beiden Werten gesetzt sind:
         00000000000000000111011111110111

Eine andere Möglichkeit dies zu bewerkstelligen, ist XOR (`^`) zu verwenden, um diejenigen Bits zu finden, die nur in einem der beiden Werte gesetzt sind: `E_ALL ^ E_NOTICE`

error_reporting kann ebenfalls verwendet werden, um zu zeigen, wie Bits gesetzt werden. Auf folgende Weise werden nur Fehler und behebbare Fehler angezeigt: `E_ERROR | E_RECOVERABLE_ERROR`

         Dieser Vorgang kombiniert E_ERROR
         00000000000000000000000000000001
         und
         00000000000000000001000000000000
         unter Verwendung des OR- (|) Operators
         um die Bits zu ermitteln, die in einem oder beiden Werten gesetzt sind:
         00000000000000000001000000000001

Beispiel #1 Bitweise AND, OR und XOR Operationen mit Ganzzahlen

    <?php
    /*
     * Der erste Abschnitt kann ignoriert werden;
     * er dient nur zu Formatierungszwecken, um die Ausgabe deutlicher zu machen.
     */

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

    echo <<<EOH
     ---------     ---------  -- ---------
     Ergebnis      Wert 1     Op Wert 2
     ---------     ---------  -- ---------
    EOH;

    /*
     * Hier kommen die Beispiele.
     */

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

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

    echo "\n Bitweises einschließendes OR \n";
    foreach ($values as $value) {
        $result = $value | $test;
        printf($format, $result, $value, '|', $test);
    }

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

Das oben gezeigte Beispiel erzeugt folgende Ausgabe:

     ---------     ---------  -- ---------
     Ergebnis      Wert 1     Op Wert 2
    ---------     ---------  -- ---------
     Bitweises 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)

     Bitweises einschließendes 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)

     Bitweises ausschließendes 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)

Beispiel #2 Bitweise XOR-Operationen mit Zeichenketten

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

    echo "12" ^ "9", PHP_EOL; // Gibt das Backspace-Zeichen (ascii 8) aus
                              // ('1' (ascii 49)) ^ ('9' (ascii 57)) = #8

    echo "hallo" ^ "hello", PHP_EOL; // Gibt die ascii-Werte #0 #4 #0 #0 #0 aus
                                     // 'a' ^ 'e' = #4

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

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

Beispiel #3 Bit-Verschiebung mit Ganzzahlen

    <?php
    /*
     * Hier kommen die Beispiele.
     */

    echo "\n--- RECHTSVERSCHIEBUNG MIT POSITIVEN GANZZAHLEN ---\n";

    $val = 4;
    $places = 1;
    $res = $val >> $places;
    p($res, $val, '>>', $places, 'Kopie des Vorzeichenbits wird links hereingeschoben');

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

    $val = 4;
    $places = 3;
    $res = $val >> $places;
    p($res, $val, '>>', $places, 'Bits werden rechts herausgeschoben');

    $val = 4;
    $places = 4;
    $res = $val >> $places;
    p($res, $val, '>>', $places, 'dasselbe Ergebnis wie oben; man kann nicht über 0 hinaus verschieben');

    echo "\n--- RECHTSVERSCHIEBUNG MIT NEGATIVEN GANZZAHLEN ---\n";

    $val = -4;
    $places = 1;
    $res = $val >> $places;
    p($res, $val, '>>', $places, 'Kopie des Vorzeichenbits wird links hereingeschoben');

    $val = -4;
    $places = 2;
    $res = $val >> $places;
    p($res, $val, '>>', $places, 'Bits werden rechts herausgeschoben');

    $val = -4;
    $places = 3;
    $res = $val >> $places;
    p($res, $val, '>>', $places, 'dasselbe Ergebnis wie oben; man kann nicht über -1 hinaus verschieben');

    echo "\n--- LINKSSVERSCHIEBUNG MIT POSITIVEN GANZZAHLEN ---\n";

    $val = 4;
    $places = 1;
    $res = $val << $places;
    p($res, $val, '<<', $places, 'Nullen werden rechts hereingeschoben');

    $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, 'Vorzeichenbits werden herausgeschoben');

    $val = 4;
    $places = (PHP_INT_SIZE * 8) - 2;
    $res = $val << $places;
    p($res, $val, '<<', $places, 'Bits werden links herausgeschoben');

    echo "\n--- LINKSVERSCHIEBUNG MIT NEGATIVEN GANZZAHLEN ---\n";

    $val = -4;
    $places = 1;
    $res = $val << $places;
    p($res, $val, '<<', $places, 'Nullen werden rechts hereingeschoben');

    $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, 'Bits werden links herausgeschoben, einschließlich des Vorzeichenbits');

    /*
     * Dieser Abschnitt kann ignoriert werden;
     * es handlet sich nur um Formatierung, um die Ausgabe deutlicher zu machen.
     */

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

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

        echo " Dezimal:\n";
        printf("  Wert=%d\n", $val);
        printf("  Erg.=%d\n", $res);

        echo " Binär:\n";
        printf('  Wert=' . $format, $val);
        printf('  Erg.=' . $format, $res);

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

        echo "\n\n";
    }
    ?>

Das oben gezeigte Beispiel erzeugt auf 32-Bit-Systemen folgende Ausgabe:

    --- RECHTSVERSCHIEBUNG MIT POSITIVEN GANZZAHLEN ---
    Ausdruck: 2 = 4 >> 1
     Dezimal:
      Wert=4
      Erg.=2
     Binär:
      Wert=00000000000000000000000000000100
      Erg.=00000000000000000000000000000010
     ANMERKUNG: Kopie des Vorzeichenbits wird links hereingeschoben

    Ausdruck: 1 = 4 >> 2
     Dezimal:
      Wert=4
      Erg.=1
     Binär:
      Wert=00000000000000000000000000000100
      Erg.=00000000000000000000000000000001

    Ausdruck: 0 = 4 >> 3
     Dezimal:
      Wert=4
      Erg.=0
     Binär:
      Wert=00000000000000000000000000000100
      Erg.=00000000000000000000000000000000
     ANMERKUNG: Bits werden rechts herausgeschoben

    Ausdruck: 0 = 4 >> 4
     Dezimal:
      Wert=4
      Erg.=0
     Binär:
      Wert=00000000000000000000000000000100
      Erg.=00000000000000000000000000000000
     ANMERKUNG: dasselbe Ergebnis wie oben; man kann nicht über 0 hinaus verschieben

    --- RECHTSVERSCHIEBUNG MIT NEGATIVEN GANZZAHLEN ---
    Ausdruck: -2 = -4 >> 1
     Dezimal:
      Wert=-4
      Erg.=-2
     Binär:
      Wert=11111111111111111111111111111100
      Erg.=11111111111111111111111111111110
     ANMERKUNG: Kopie des Vorzeichenbits wird links hereingeschoben

    Ausdruck: -1 = -4 >> 2
     Dezimal:
      Wert=-4
      Erg.=-1
     Binär:
      Wert=11111111111111111111111111111100
      Erg.=11111111111111111111111111111111
     ANMERKUNG: Bits werden rechts herausgeschoben

    Ausdruck: -1 = -4 >> 3
     Dezimal:
      Wert=-4
      Erg.=-1
     Binär:
      Wert=11111111111111111111111111111100
      Erg.=11111111111111111111111111111111
     ANMERKUNG: dasselbe Ergebnis wie oben; man kann nicht über -1 hinaus verschieben

    --- LINKSSVERSCHIEBUNG MIT POSITIVEN GANZZAHLEN ---
    Ausdruck: 8 = 4 << 1
     Dezimal:
      Wert=4
      Erg.=8
     Binär:
      Wert=00000000000000000000000000000100
      Erg.=00000000000000000000000000001000
     ANMERKUNG: Nullen werden rechts hereingeschoben

    Ausdruck: 1073741824 = 4 << 28
     Dezimal:
      Wert=4
      Erg.=1073741824
     Binär:
      Wert=00000000000000000000000000000100
      Erg.=01000000000000000000000000000000

    Ausdruck: -2147483648 = 4 << 29
     Dezimal:
      Wert=4
      Erg.=-2147483648
     Binär:
      Wert=00000000000000000000000000000100
      Erg.=10000000000000000000000000000000
     ANMERKUNG: Vorzeichenbits werden herausgeschoben

    Ausdruck: 0 = 4 << 30
     Dezimal:
      Wert=4
      Erg.=0
     Binär:
      Wert=00000000000000000000000000000100
      Erg.=00000000000000000000000000000000
     ANMERKUNG: Bits werden links herausgeschoben

    --- LINKSVERSCHIEBUNG MIT NEGATIVEN GANZZAHLEN ---
    Ausdruck: -8 = -4 << 1
     Dezimal:
      Wert=-4
      Erg.=-8
     Binär:
      Wert=11111111111111111111111111111100
      Erg.=11111111111111111111111111111000
     ANMERKUNG: Nullen werden rechts hereingeschoben

    Ausdruck: -2147483648 = -4 << 29
     Dezimal:
      Wert=-4
      Erg.=-2147483648
     Binär:
      Wert=11111111111111111111111111111100
      Erg.=10000000000000000000000000000000

    Ausdruck: 0 = -4 << 30
     Dezimal:
      Wert=-4
      Erg.=0
     Binär:
      Wert=11111111111111111111111111111100
      Erg.=00000000000000000000000000000000
     ANMERKUNG: Bits werden links herausgeschoben, einschließlich des Vorzeichenbits

Das oben gezeigte Beispiel erzeugt auf 64-Bit-Systemen folgende Ausgabe:

    --- RECHTSVERSCHIEBUNG MIT POSITIVEN GANZZAHLEN ---
    Ausdruck: 2 = 4 >> 1
     Dezimal:
      Wert=4
      Erg.=2
     Binär:
      Wert=0000000000000000000000000000000000000000000000000000000000000100
      Erg.=0000000000000000000000000000000000000000000000000000000000000010
     ANMERKUNG: Kopie des Vorzeichenbits wird links hereingeschoben

    Ausdruck: 1 = 4 >> 2
     Dezimal:
      Wert=4
      Erg.=1
     Binär:
      Wert=0000000000000000000000000000000000000000000000000000000000000100
      Erg.=0000000000000000000000000000000000000000000000000000000000000001

    Ausdruck: 0 = 4 >> 3
     Dezimal:
      Wert=4
      Erg.=0
     Binär:
      Wert=0000000000000000000000000000000000000000000000000000000000000100
      Erg.=0000000000000000000000000000000000000000000000000000000000000000
     ANMERKUNG: Bits werden rechts herausgeschoben

    Ausdruck: 0 = 4 >> 4
     Dezimal:
      Wert=4
      Erg.=0
     Binär:
      Wert=0000000000000000000000000000000000000000000000000000000000000100
      Erg.=0000000000000000000000000000000000000000000000000000000000000000
     ANMERKUNG: dasselbe Ergebnis wie oben; man kann nicht über 0 hinaus verschieben

    --- RECHTSVERSCHIEBUNG MIT NEGATIVEN GANZZAHLEN ---
    Ausdruck: -2 = -4 >> 1
     Dezimal:
      Wert=-4
      Erg.=-2
     Binär:
      Wert=1111111111111111111111111111111111111111111111111111111111111100
      Erg.=1111111111111111111111111111111111111111111111111111111111111110
     ANMERKUNG: Kopie des Vorzeichenbits wird links hereingeschoben

    Ausdruck: -1 = -4 >> 2
     Dezimal:
      Wert=-4
      Erg.=-1
     Binär:
      Wert=1111111111111111111111111111111111111111111111111111111111111100
      Erg.=1111111111111111111111111111111111111111111111111111111111111111
     ANMERKUNG: Bits werden rechts herausgeschoben

    Ausdruck: -1 = -4 >> 3
     Dezimal:
      Wert=-4
      Erg.=-1
     Binär:
      Wert=1111111111111111111111111111111111111111111111111111111111111100
      Erg.=1111111111111111111111111111111111111111111111111111111111111111
     ANMERKUNG: dasselbe Ergebnis wie oben; man kann nicht über -1 hinaus verschieben

    --- LINKSSVERSCHIEBUNG MIT POSITIVEN GANZZAHLEN ---
    Ausdruck: 8 = 4 << 1
     Dezimal:
      Wert=4
      Erg.=8
     Binär:
      Wert=0000000000000000000000000000000000000000000000000000000000000100
      Erg.=0000000000000000000000000000000000000000000000000000000000001000
     ANMERKUNG: Nullen werden rechts hereingeschoben

    Ausdruck: 4611686018427387904 = 4 << 60
     Dezimal:
      Wert=4
      Erg.=4611686018427387904
      Binär:
      Wert=0000000000000000000000000000000000000000000000000000000000000100
      Erg.=0100000000000000000000000000000000000000000000000000000000000000

    Ausdruck: -9223372036854775808 = 4 << 61
     Dezimal:
      Wert=4
      Erg.=-9223372036854775808
     Binär:
      Wert=0000000000000000000000000000000000000000000000000000000000000100
      Erg.=1000000000000000000000000000000000000000000000000000000000000000
     ANMERKUNG: Vorzeichenbits werden herausgeschoben

    Ausdruck: 0 = 4 << 62
     Dezimal:
      Wert=4
      Erg.=0
     Binär:
      Wert=0000000000000000000000000000000000000000000000000000000000000100
      Erg.=0000000000000000000000000000000000000000000000000000000000000000
     ANMERKUNG: Bits werden links herausgeschoben

    --- LINKSVERSCHIEBUNG MIT NEGATIVEN GANZZAHLEN ---
    Ausdruck: -8 = -4 << 1
     Dezimal:
      Wert=-4
      Erg.=-8
     Binär:
      Wert=1111111111111111111111111111111111111111111111111111111111111100
      Erg.=1111111111111111111111111111111111111111111111111111111111111000
     ANMERKUNG: Nullen werden rechts hereingeschoben

    Ausdruck: -9223372036854775808 = -4 << 61
     Dezimal:
      Wert=-4
      Erg.=-9223372036854775808
     Binär:
      Wert=1111111111111111111111111111111111111111111111111111111111111100
      Erg.=1000000000000000000000000000000000000000000000000000000000000000

    Ausdruck: 0 = -4 << 62
     Dezimal:
      Wert=-4
      Erg.=0
     Binär:
      Wert=1111111111111111111111111111111111111111111111111111111111111100
      Erg.=0000000000000000000000000000000000000000000000000000000000000000
     ANMERKUNG: Bits werden links herausgeschoben, einschließlich des Vorzeichenbits

Warnung

Für die bitweise Manipulation von Zahlen größer als `PHP_INT_MAX` sind die Funktion der GMP-Erweiterung zu verwenden.

### Siehe auch

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

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