Skip to content

Operators

There is no operator overloading. When you see an operator in Zig, you know that it is doing something from below, and nothing else.

Addition

zig
a + b
a += b
  • Can cause overflow for integers.
  • Invokes Peer Type Resolution for the operands.
  • See also @addWithOverflow.
zig
2 + 5 == 7

Wrapping Addition

zig
a +% b
a +%= b
  • Twos-complement wrapping behavior.
  • Invokes Peer Type Resolution for the operands.
  • See also @addWithOverflow.
zig
@as(u32, 0xffffffff) +% 1 == 0

Saturating Addition

zig
a +| b
a +|= b
  • Invokes Peer Type Resolution for the operands.
zig
@as(u8, 255) +| 1 == @as(u8, 255)

Subtraction

zig
a - b
a -= b
  • Can cause overflow for integers.
  • Invokes Peer Type Resolution for the operands.
  • See also @subWithOverflow.
zig
2 - 5 == -3

Wrapping Subtraction

zig
a -% b
a -%= b
  • Twos-complement wrapping behavior.
  • Invokes Peer Type Resolution for the operands.
  • See also @subWithOverflow.
zig
@as(u8, 0) -% 1 == 255

Saturating Subtraction

zig
a -| b
a -|= b
  • Invokes Peer Type Resolution for the operands.
zig
@as(u32, 0) -| 1 == 0

Negation

zig
-a
  • Can cause overflow for integers.
zig
-1 == 0 - 1

Wrapping Negation

zig
-%a
  • Twos-complement wrapping behavior.
zig
-%@as(i8, -128) == -128

Multiplication

zig
a * b
a *= b
  • Can cause overflow for integers.
  • Invokes Peer Type Resolution for the operands.
  • See also @mulWithOverflow.
zig
2 * 5 == 10

Wrapping Multiplication

zig
a *% b
a *%= b
  • Twos-complement wrapping behavior.
  • Invokes Peer Type Resolution for the operands.
  • See also @mulWithOverflow.
zig
@as(u8, 200) *% 2 == 144

Saturating Multiplication

zig
a *| b
a *|= b
  • Invokes Peer Type Resolution for the operands.
zig
@as(u8, 200) *| 2 == 255

Division

zig
a / b
a /= b
  • Can cause overflow for integers.
  • Can cause Division by Zero for integers.
  • Can cause Division by Zero for floats in FloatMode.Optimized Mode.
  • Signed integer operands must be comptime-known and positive.
  • In other cases, use @divTrunc, @divFloor, or @divExact instead.
  • Invokes Peer Type Resolution for the operands.
zig
10 / 5 == 2

Remainder Division

zig
a % b
a %= b
  • Can cause Division by Zero for integers.
  • Can cause Division by Zero for floats in FloatMode.Optimized Mode.
  • Signed or floating-point operands must be comptime-known and positive. In other cases, use @rem or @mod instead.
  • Invokes Peer Type Resolution for the operands.
zig
10 % 3 == 1

Bit Shift Left

zig
a << b
a <<= b
  • Moves all bits to the left, inserting new zeroes at the least-significant bit.
  • b must be comptime-known or have a type with log2 number of bits as a.
  • See also @shlExact.
  • See also @shlWithOverflow.
zig
0b1 << 8 == 0b100000000

Saturating Bit Shift Left

zig
a <<| b
a <<|= b
zig
@as(u8, 1) <<| 8 == 255

Bit Shift Right

zig
a >> b
a >>= b
  • Moves all bits to the right, inserting zeroes at the most-significant bit.
  • b must be comptime-known or have a type with log2 number of bits as a.
  • See also @shrExact.
zig
0b1010 >> 1 == 0b101

Bitwise And

zig
a & b
a &= b
  • Invokes Peer Type Resolution for the operands.
zig
0b011 & 0b101 == 0b001

Bitwise Or

zig
a | b
a |= b
  • Invokes Peer Type Resolution for the operands.
zig
0b010 | 0b100 == 0b110

Bitwise Xor

zig
a ^ b
a ^= b
  • Invokes Peer Type Resolution for the operands.
zig
0b011 ^ 0b101 == 0b110

Bitwise Not

zig
~a
zig
~@as(u8, 0b10101111) == 0b01010000

Defaulting Optional Unwrap

zig
a orelse b
  • If a is null, returns b ("default value"), otherwise returns the unwrapped value of a. Note that b may be a value of type noreturn.
zig
const value: ?u32 = null;
const unwrapped = value orelse 1234;
unwrapped == 1234

Optional Unwrap

zig
a.?
  • Equivalent to: a orelse unreachable
zig
const value: ?u32 = 5678;
value.? == 5678

Defaulting Error Unwrap

zig
a catch b
a catch |err| b
  • If a is an error, returns b ("default value"), otherwise returns the unwrapped value of a. Note that b may be a value of type noreturn. err is the error and is in scope of the expression b.
zig
const value: anyerror!u32 = error.Broken;
const unwrapped = value catch 1234;
unwrapped == 1234

Logical And

zig
a and b
  • If a is false, returns false without evaluating b. Otherwise, returns b.
zig
(false and true) == false

Logical Or

zig
a or b
  • If a is true, returns true without evaluating b. Otherwise, returns b.
zig
(false or true) == true

Boolean Not

zig
!a
zig
!false == true

Equality

zig
a == b
  • Returns true if a and b are equal, otherwise returns false.
  • Invokes Peer Type Resolution for the operands.
zig
(1 == 1) == true

Null Check

zig
a == null
  • Returns true if a is null, otherwise returns false.
zig
const value: ?u32 = null;
(value == null) == true

Inequality

zig
a != b
  • Returns false if a and b are equal, otherwise returns true. Invokes Peer Type Resolution for the operands.
zig
(1 != 1) == false

Non-Null Check

zig
a != null
  • Returns false if a is null, otherwise returns true.
zig
const value: ?u32 = null;
(value != null) == false

Greater Than

zig
a > b
  • Returns true if a is greater than b, otherwise returns false. Invokes Peer Type Resolution for the operands.
zig
(2 > 1) == true

Greater or Equal

zig
a >= b
  • Returns true if a is greater than or equal to b, otherwise returns false. Invokes Peer Type Resolution for the operands.
zig
(2 >= 1) == true

Less Than

zig
a < b
  • Returns true if a is less than b, otherwise returns false. Invokes Peer Type Resolution for the operands.
zig
(1 < 2) == true

Lesser or Equal

zig
a <= b
  • Returns true if a is less than or equal to b, otherwise returns false. Invokes Peer Type Resolution for the operands.
zig
(1 <= 2) == true

Array Concatenation

zig
a ++ b
  • Only available when the lengths of both a and b are compile-time known.
zig
const mem = @import("std").mem;
const array1 = [_]u32{1,2};
const array2 = [_]u32{3,4};
const together = array1 ++ array2;
mem.eql(u32, &together, &[_]u32{1,2,3,4})

Array Multiplication

zig
a ** b
  • Only available when the length of a and b are compile-time known.
zig
const mem = @import("std").mem;
const pattern = "ab" ** 3;
mem.eql(u8, pattern, "ababab")

Pointer Dereference

zig
a.*
zig
const x: u32 = 1234;
const ptr = &x;
ptr.* == 1234

Address Of

zig
&a
zig
const x: u32 = 1234;
const ptr = &x;
ptr.* == 1234

Error Set Merge

zig
a || b
zig
const A = error{One};
const B = error{Two};
(A || B) == error{One, Two}

Precedence

zig
x() x[] x.y x.* x.?
a!b
x{}
!x -x -%x ~x &x ?x
* / % ** *% *| ||
+ - ++ +% -% +| -|
<< >> <<|
& ^ | orelse catch
== != < > <= >=
and
or
= *= *%= *|= /= %= += +%= +|= -= -%= -|= <<= <<|= >>= &= ^= |=