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