Originally published on php2rust.dev — part of the PHP to Rust course. View this lesson on the original site.
Rust offers many integer types with fixed sizes. PHP has a single int type (usually 64-bit).
Rust integer types
What do the numbers (8, 16, 32, …) mean?
The suffix on each type is the width of the value in bits, how many binary digits Rust uses to store one number of that type in memory.
i32→ 32 bits (4 bytes) per valuei64→ 64 bits (8 bytes) per value- Same idea for
i8,i16,i128, and allu*types.
More bits mean a larger range of representable integers (and more memory per variable). The type is fixed: an i16 cannot silently grow to hold a bigger number; if a computation overflows, behaviour depends on build mode (panic in debug, wrap in release unless you use checked APIs, covered later in the course).
i8 vs i16 vs i32 …, what actually changes?
Only width (and therefore range and stack / struct size). i8 through i128 all mean “signed integer”; the language doesn’t give i64 different operators from i8. You pick a type so every value you need fits without overflow and so you don’t waste space or mismatch a foreign API (e.g. a C struct field is int32_t → use i32).
Unsigned types follow the same pattern: u8 vs u16 vs u32 is still “how many bits,” with u meaning “non-negative only.” A u16 is not the same numeric range as i16: both use 16 bits, but one bit pattern is reserved for sign in i16, so max values differ.
Signed (i*) types use one bit for sign; roughly half the patterns are negative, half non-negative:
- Range for
iN: −2^(N−1) through 2^(N−1) − 1 (for examplei32: −2^31 … 2^31 − 1)
Unsigned (u*) types store only zero and positive whole numbers; all bits contribute to magnitude:
- Range for
uN: 0 through 2^N − 1
Ranges at a glance
| Type | Bits | Approximate range |
|---|---|---|
i8 |
8 | −128 … 127 |
i16 |
16 | −32_768 … 32_767 |
i32 |
32 | −2_147_483_648 … 2_147_483_647 |
i64 |
64 | about ±9.2 × 10^18 |
i128 |
128 | enormous (good for cryptography, timestamps, big aggregates) |
u8 |
8 | 0 … 255 |
u16 |
16 | 0 … 65_535 |
u32 |
32 | 0 … 4_294_967_295 |
u64 |
64 | 0 … about 1.84 × 10^19 |
u128 |
128 | 0 … very large |
i32 is the default when you write an integer literal and the compiler infers an integer type, it’s a good balance of range and size on all platforms.
Choosing a width
i8/u8: tiny counts, raw bytes, compact structs, binary protocols (e.g. one byte per channel 0–255).i16/u16: small IDs, audio samples, legacy file formats.i32/u32: general arithmetic, loop counters, many APIs (Unix error codes asi32, IPv4 addresses asu32, etc.).i64/u64: file sizes, timestamps in nanoseconds, anything that can exceedi32’s ~2.1 billion.i128/u128: when you need even more headroom without switching to a big-int crate yet.
isize and usize
These are pointer-sized: on a 64-bit program they behave like 64-bit integers for width; on 32-bit, like 32-bit. Use them for memory indexing, lengths and indices of slices, vectors, and arrays, so they always match what the platform can address.
fn main() {
let a: i32 = -42;
let b: u32 = 42;
let c: u8 = 255;
let index: usize = 0; // Idiomatic for array/slice indices
// Literal suffixes
let d = 100i64;
let e = 1_000_000_u32; // Underscores for readability
println!("a={}, b={}, c={}, index={}, d={}, e={}", a, b, c, index, d, e);
}
PHP integers
PHP has one integer type, typically 64-bit signed:
<?php
$a = -42;
$b = 42;
$c = 255;
// PHP 7.4+: underscore in numeric literals
$e = 1_000_000;
echo "a=$a, b=$b, c=$c, e=$e\n";
// Overflow becomes float
$big = PHP_INT_MAX + 1; // Becomes float on 64-bit
var_dump($big); // float(9.223372036854776E+18)
PHP does not have unsigned integers or fixed-size types. Overflow converts to float.
Comparison
- Rust: The number in the type name is the bit width; range follows from that. You choose
i8…i128/u8…u128explicitly;isize/usizematch the address space. Overflow is explicit (panic, wrap, or checked math, not silent growth). - PHP: Single
inttype; the engine picks a width (often 64-bit signed on modern PHP). You don’t declareint8vsint64. Overflow can becomefloat. No unsigned integers in the type system.
References
What's next
Next: Floating-point numbers.
From PHP to Rust — Rust Syntax and Functions