Bitwise Operators

suggest change

Prefix bitwise operators

Bitwise operators are like logical operators but executed per bit rather than per boolean value.

// bitwise NOT ~: sets all unset bits and unsets all set bits
printf("%'06b", ~0b110110); // 001001

Bitmask-bitmask operators

Bitwise AND &: a bit is set only if it is set in both operands

printf("%'06b", 0b110101 & 0b011001); // 010001

Bitwise OR |: a bit is set if it is set in either or both operands

printf("%'06b", 0b110101 | 0b011001); // 111101

Bitwise XOR ^: a bit is set if it is set in one operand and not set in another operand, i.e. only if that bit is in different state in the two operands

printf("%'06b", 0b110101 ^ 0b011001); // 101100

Example uses of bitmasks

These operators can be used to manipulate bitmasks. For example:

file_put_contents("file.log", LOCK_EX | FILE_APPEND);

Here, the | operator is used to combine the two bitmasks. Although \+ has the same effect, | emphasizes that you are combining bitmasks, not adding two normal scalar integers.

class Foo{
    const OPTION_A = 1;
    const OPTION_B = 2;
    const OPTION_C = 4;
    const OPTION_A = 8;

    private $options = self::OPTION_A | self::OPTION_C;

    public function toggleOption(int $option){
        $this->options ^= $option;
    }

    public function enable(int $option){
        $this->options |= $option; // enable $option regardless of its original state
    }

    public function disable(int $option){
        $this->options &= ~$option; // disable $option regardless of its original state,
                                    // without affecting other bits
    }

    /** returns whether at least one of the options is enabled */
    public function isOneEnabled(int $options) : bool{
        return $this->options & $option !== 0;
        // Use !== rather than >, because 
        // if $options is about a high bit, we may be handling a negative integer
    }

    /** returns whether all of the options are enabled */
    public function areAllEnabled(int $options) : bool{
        return ($this->options & $options) === $options;
        // note the parentheses; beware the operator precedence
    }
}

This example (assuming $option always only contain one bit) uses:

Bear in mind that these comparison operators: (\< \> <= >= == === != !== <> <=>) have higher precedence than these bitmask-bitmask operators: (| ^ &). As bitwise results are often compared using these comparison operators, this is a common pitfall to be aware of.

Bit-shifting operators

Bitwise left shift <<: shift all bits to the left (more significant) by the given number of steps and discard the bits exceeding the int size

<< $x is equivalent to unsetting the highest $x bits and multiplying by the $xth power of 2

printf("%'08b", 0b00001011<< 2); // 00101100

assert(PHP_INT_SIZE === 4); // a 32-bit system
printf("%x, %x", 0x5FFFFFFF << 2, 0x1FFFFFFF << 4); // 7FFFFFFC, FFFFFFFF

Bitwise right shift >>: discard the lowest shift and shift the remaining bits to the right (less significant)

>> $x is equivalent to dividing by the $xth power of 2 and discard the non-integer part

printf("%x", 0xFFFFFFFF >> 3); // 1FFFFFFF

Example uses of bit shifting:

Fast division by 16 (better performance than /= 16)

$x >>= 4;

On 32-bit systems, this discards all bits in the integer, setting the value to 0. On 64-bit systems, this unsets the most significant 32 bits and keep the least

$x = $x << 32 >> 32;

significant 32 bits, equivalent to $x & 0xFFFFFFFF

Note: In this example, printf("%'06b") is used. It outputs the value in 6 binary digits.

Feedback about page:

Feedback:
Optional: your email if you want me to get back to you:


Operators:
* Bitwise Operators

Table Of Contents
2 Arrays
4 Types
10 Cookies
14 JSON
15 SOAP
17 cURL
19 XML
21 Traits
33 Operators
35 UTF-8
36 URLs
38 PHPDoc
41 Loops
44 Closur
72 YAML
77 Cache
78 Streams
81 PDO
82 SQLite3
83 Sockets
87 MongoDB
93 IMAP
94 Redis
95 Imagick
102 APCu
108 PSR