# 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
``````

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
``````

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:

• the `^` operator to conveniently toggle bitmasks.
• the `|` operator to set a bit neglecting its original state or other bits
• the `~` operator to convert an integer with only one bit set into an integer with only one bit not set
• the `&` operator to unset a bit, using these properties of `&`:
• Since `&=` with a set bit will not do anything (`(1 & 1) === 1`, `(0 & 1) === 0`), doing `&=` with an integer with only one bit not set will only unset that bit, not affecting other bits.
• `&=` with an unset bit will unset that bit (`(1 & 0) === 0`, `(0 & 0) === 0`)
• Using the `&` operator with another bitmask will filter away all other bits not set in that bitmask.
• If the output has any bits set, it means that any one of the options are enabled.
• If the output has all bits of the bitmask set, it means that all of the options in the bitmask are enabled.

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 `\$x`th 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 `\$x`th 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. PDF - Download PHP for free