⚡ Zig Guide LiveUnofficial
✓ Zig 0.17.0-dev.1454+5faa79730On an older Zig?

Pointer Sized Integers

const std = @import("std");
const expect = std.testing.expect;

test "usize matches pointer width" {
    try expect(@sizeOf(usize) == @sizeOf(*u8));
    try expect(@sizeOf(isize) == @sizeOf(*u8));
}

test "usize is the index and length type" {
    // `.len` is a usize, and so is anything used to index a slice.
    const array = [_]u8{ 1, 2, 3 };
    const length: usize = array.len;
    try expect(length == 3);
    try expect(@TypeOf(array.len) == usize);
}

test "wasm32 is a 32-bit target" {
    // These snippets are compiled to wasm32-wasi, so a pointer is 4 bytes.
    // The same source on x86_64 would see 8.
    try expect(@sizeOf(usize) == 4);
}

usize and isize are exactly as wide as a pointer on the target. They are the types of .len and of anything used to index a slice.

They are target-dependent, and that is the point

The snippets on this site compile to wasm32-wasi, so @sizeOf(usize) is 4. Build the identical source for x86_64 and it is 8. That is why the last test above asserts 4: it is a fact about the target, not about Zig.

Writing u64 where you mean usize produces code that works on your machine and breaks on a 32-bit one. Writing usize where you mean “a 64-bit counter” produces code that silently narrows on wasm. The distinction is worth keeping straight.

Converting

Integer casts are never implicit when they could lose information, so going between usize and a fixed width is explicit:

const n: u32 = @intCast(slice.len);   // checked in safety builds