Bitwise

The bitwise operators work on the individual bits of their operands.

OperatorOperationCompound formLevel
~not (prefix)—16
&and&=9
^exclusive or^=8
|or|=7
let a: uint8 = 0b00001100;
let b: uint8 = 0b00001010;
PrintLine("{} {} {} {}", a & b, a | b, a ^ b, ~a);

This prints 8 14 6 243: the bits set in both, in either, in exactly one, and every bit of a inverted.

Operand types

Operand& | ^~
integersbit by bitinverts every bit
boollogical and, or, exclusive or — both sides runlogical not
charactersbit by bit on the code—

The two operands follow the operand rules: one type, a literal that takes the other operand's type, or two integers of one signedness, where the narrower widens. A floating-point operand is refused:

error: operator '&' requires an integer, bool, or character left operand, but found 'float64'
error: operator '~' requires an integer or bool operand, but found 'float64'

Unsigned integers are the natural home for bit work, since none of their bits is a sign. On bool, & and | are the non-short-circuiting forms of && and || — see Logical.

Precedence

The binary bitwise operators bind more loosely than the comparisons, and among themselves & binds most tightly, then ^, then |. A test of a masked value therefore needs parentheses:

let x: int32 = 6;
let even = x & 1 == 0;

This groups as x & (1 == 0):

error: operator '&' cannot combine left operand 'int32' with right operand 'bool8'

Write (x & 1) == 0. Shifts and arithmetic bind more tightly than all three, so flags & 1 << 2 is flags & (1 << 2); parentheses still make it easier to read.

Masks and flags

With a shift to build the mask, the four single-bit operations are:

var flags: uint32 = 0;
flags |= 1 << 3;
flags &= ~(1u32 << 3);
flags ^= 1 << 2;
let isSet = (flags & (1 << 2)) != 0;

|= sets bit 3, &= with the inverted mask clears it, ^= toggles bit 2, and the last line tests it. The 1u32 in the clearing mask gives ~ a uint32 to invert. With an unsuffixed 1, ~(1 << 3) is an int, and flags &= ~(1 << 3) is error: operator '&=' cannot combine left operand 'uint32' with right operand 'int'.

Compound forms

&=, |= and ^= update a mutable place: flags |= mask is flags = flags | mask. The target must be a var or another writable place — see Assignment.

See also