I32 vs isize, u32 vs usize

I’m grateful for all Rust type errors – because it is preventing me from doing stupid things.

However, I find u32 vs usize and i32 vs isize very confusing. What is the guideline for when something is a Xsize vs a X32 ?


Hi, I’m new to Rust too.
In my opinion, u32 and i32 are fixed bytes length (width), usize and isize depends on architecture (x64 or x86)

1 Like

Use usize and isize when it’s related to memory size – the size of an object, or indexing a vector, for instance. It will be a 32-bit number on 32-bit platforms, as that’s the limit of memory they can address, and likewise for 64-bit.

Use u32 and i32 when you just want numbers.


If the number has something to do with the size of the address space of the target platform, use *size. If the number fits within 32-bits, use *32. If you don’t know either way, you don’t know what your code is supposed to be doing well enough; think about it some more.

If you still can’t decide, just pick something and reassess later.


To add to the above, use i64/u64 when it’s a number not tied to the size of the memory address space, and you are not sure that all practical values (including results of intermediate calculations) can fit into 32 bits. The rule of thumb for values you might want to do arithmetics over is, your values need to be “ridiculously small” to qualify for *32.

The practical solution is to use usize for everything you can :slight_smile:

Rust only supports indexing of arrays/slices/vec using usize, so even if you try to use other types, you’ll soon find yourself casting them back and forth.


I can’t tell if this is serious:

Does usize/isize guarantee a minimum number of bits, i.e. that it’s guaranteed to be atleast 64?

It’s identical to size_t, so it’s guaranteed to be exactly 32-bit on 32-bit architectures, etc.

I’m serious, because u32 and u64 can’t be converted to usize using From, so you’re forced to use silently-truncating as, which may hide type mistakes and therefore is bug-prone.

Yes, as usize is boring. But sometimes it’s worth using u32 to lower the memory footprint.

… or 16-bit if anyone ever compiles your code on a 16-bit architecture.
Seriously, don’t use isize/usize to represent anything other than in-memory collection sizes, offsets, and the like. I would discourage use of a library that abuses memory-sized integer types to represent any problem domain integers.

This is where you should give yourself pause and ask yourself why do you need to do this, and whether this can fail, and what to do in this case. There is an unstable TryFrom trait in the standard library that will help make things more ergonomic.


Thanks to everyone for replies.

I rewrote my codebase with:

  • isize;/usize for everything that is: memory size, index, offset related
  • i32/u32/i64/u64: for actual ints, as appropriate

Everything feels much more principled / clear. Thanks for guidance!