Primitive types are the basic building blocks with which Rust represents simple values such as numbers, booleans, characters, or small groupings.
Rust is a statically typed language, so the compiler needs to know the type of each value before running the program. It often figures it out on its own, but it’s good to know what it’s inferring.
Integers
Integers represent numbers without decimals. Rust has signed and unsigned integers:
| Type | Approximate Range | Typical Use |
|---|---|---|
i8, i16, i32, i64, i128 | Includes negatives | Values that can be less than zero |
u8, u16, u32, u64, u128 | Zero and positives | Sizes, counters, bytes |
isize, usize | Depends on architecture | Indices and sizes of collections |
By default, Rust uses i32 when we write an integer without specifying anything else.
fn main() {
let age = 42; // i32 by default
let points: u32 = 100;
let byte: u8 = 255;
}usize appears frequently when working with vectors, arrays, and strings, because it’s the natural type for indices and sizes in memory.
Floating-Point Numbers
For numbers with decimals, we have f32 and f64.
fn main() {
let temperature = 23.5; // f64 by default
let sensor: f32 = 0.125;
}By default, Rust uses f64, as it usually offers better precision and on modern CPUs it typically doesn’t penalize too much.
Floats are not exact. Do not use f32 or f64 for money if you need strict decimal precision. For that, there are specific types or integer representation (cents, for example).
Booleans
The bool type can only be true or false.
fn main() {
let active = true;
let finished: bool = false;
}It is used in conditionals, flags, and any situation where we want to express yes/no, on/off, or true/false.
Characters
The char type represents a Unicode character, not simply a byte.
fn main() {
let letter = 'a';
let symbol = 'ñ';
let emoji = '🦀';
}In Rust, a char occupies 4 bytes, because it can represent any valid Unicode value.
Tuples
A tuple groups several values of different types into a single structure.
fn main() {
let person = ("Luis", 42, true);
let name = person.0;
let age = person.1;
let active = person.2;
}We can also destructure it:
fn main() {
let point = (10, 20);
let (x, y) = point;
println!("x={}, y={}", x, y);
}Tuples are useful for returning several small values without creating a struct yet.
Arrays
An array stores multiple values of the same type with a fixed length.
fn main() {
let numbers = [1, 2, 3, 4, 5];
let first = numbers[0];
}We can also specify type and size:
let sensors: [i32; 4] = [10, 20, 30, 40];And create an array by repeating a value:
let buffer = [0; 1024]; // 1024 zerosAn array is not a vector. The array has a fixed size known at compile time. The vector (Vec<T>) can grow, and we will see it later.
Type Annotations
Rust infers types very well, but sometimes we need to help it:
fn main() {
let number: u64 = "42".parse().expect("Not a number");
}Without : u64, the compiler wouldn’t know what numeric type we want to obtain with parse.