Bitwise operators#

The boolean operators applied to each pair of bits in parallel, plus the two shifts. A 32- or 64-bit integer is, from these operators« point of view, a vector of independent one-bit values.

Operator

Operation

Per-bit rule

&

bitwise AND

each output bit = a b

|

bitwise OR

each output bit = a b

^

bitwise XOR

each output bit = a b

~

bitwise NOT

each output bit = ¬a (unary)

<<

left shift

shift bits left, zero-fill from right

>>

right shift

shift bits right

Operands are coerced to integers (the floor toward zero, with warnings if a non-integer string is supplied under use warnings).

0xFF & 0x0F           # 0x0F     -- mask to low nibble
0x10 | 0x01           # 0x11     -- combine flag bits
0xFF ^ 0xAA           # 0x55     -- toggle alternating bits
~0                    # -1 (or all-ones, depending on integer width)
1  << 4               # 16
32 >> 2               # 8

Setting, clearing, toggling, testing a flag#

The four basic flag operations on a single bit:

use constant FLAG_VERBOSE  => 0x01;
use constant FLAG_DRY_RUN  => 0x02;
use constant FLAG_RECURSE  => 0x04;
use constant FLAG_FORCE    => 0x08;

my $flags = 0;

$flags |=  FLAG_VERBOSE;       # SET    -- OR with the bit
$flags |=  FLAG_DRY_RUN;       # SET another
$flags &= ~FLAG_DRY_RUN;       # CLEAR  -- AND with the inverted bit
$flags ^=  FLAG_VERBOSE;       # TOGGLE -- XOR with the bit
my $on = $flags & FLAG_RECURSE;# TEST   -- AND, then test truthiness

Each is a one-bit application of a boolean operator: set is bit flag, clear is bit ¬flag, toggle is bit flag, test is bit flag.

Compound assignment#

All six binary bitwise operators have compound forms:

$bits  &= $mask;       # AND-assign
$flags |= 0x01;        # OR-assign  (set bit)
$x     ^= $y;          # XOR-assign (toggle bits where $y is 1)
$x   <<= 1;            # multiply-by-2 (with overflow caveats)
$x   >>= 1;            # divide-by-2 (toward -∞ for signed values)

Shifts#

<< shifts left; >> shifts right. The number of bit positions to shift is the right operand. Shifting by a negative amount, or by an amount equal to or greater than the integer’s bit width, is implementation-defined — don’t rely on it.

For unsigned arithmetic, left-shift is multiplication by 2 ** $n (modulo overflow):

$x << 1               # like $x * 2
$x << 8               # like $x * 256

For unsigned arithmetic, right-shift is integer division by 2 ** $n:

$x >> 1               # like int($x / 2)   (for non-negative $x)
$x >> 8               # like int($x / 256)

For signed values, >> is implementation-defined — Perl does not guarantee arithmetic vs logical shift. Mask explicitly when sign matters:

($x >> 8) & 0xFF      # extract a byte at offset 8, regardless of sign

Numeric vs bytewise mode#

Perl’s bitwise operators act on integers by default. With use feature 'bitwise' (or use v5.22+), the suffixed forms &., |., ^., ~. act on strings byte-by-byte:

use feature 'bitwise';
"\x80" |. "\x01"      # "\x81"  -- single-byte string OR
"abc"  ^. "abc"       # "\0\0\0" -- bytewise XOR

The undecorated &, |, ^, ~ operators always do integer math, and string operands are coerced to numbers first. The suffixed .-forms are the way to ask for byte-string operations explicitly.

XOR-swap#

XOR has two properties — a a = 0 and a b b = a — that combine into the famous swap-without-temporary trick:

my ($a, $b) = (0xFEED, 0xBEEF);

$a ^= $b;             # a := a ⊕ b
$b ^= $a;             # b := b ⊕ (a ⊕ b)  = a
$a ^= $b;             # a := (a ⊕ b) ⊕ a  = b

# $a == 0xBEEF, $b == 0xFEED

Not faster than ($a, $b) = ($b, $a) in Perl. Worth knowing because it appears in interview folklore and embedded code, and because it is a clean illustration of the XOR identity.

Common bit tricks#

Patterns you will see in performance-sensitive code:

$x &  ($x - 1)            # $x with its lowest set bit cleared
($x & ($x - 1)) == 0      # true when $x is a power of two (and non-zero)
1 << $n                   # the integer with only bit $n set
$x & (1 << $n)            # is bit $n set in $x?
$x | (1 << $n)            # set bit $n
$x & ~(1 << $n)           # clear bit $n
$x ^ (1 << $n)            # toggle bit $n
($x >> $n) & 0xFF         # extract a byte at offset $n

Each is an exercise in tracking what each bit does — pure boolean reasoning applied 32 (or 64) times in parallel.

Tutorial cross-reference#

The boolean-logic tutorial has a longer treatment of the bitwise-as-parallel-boolean model and the application patterns above:

See also#

  • Logical — the same boolean operators on whole values.

  • Precedence&, |, ^ sit between comparison and &&/||. Almost always parenthesise around them.

  • pack, unpack, vec — perlfunc tools for bit-level work beyond what raw operators offer.