Skip to content

Data Types

A scalar type represents a single value. Rust has four primary scalar types.

Integer types encode their signedness and bit-width in the name.

SignedUnsignedWidth
i8u88-bit
i16u1616-bit
i32u3232-bit (default)
i64u6464-bit
i128u128128-bit
isizeusizepointer-width

The default integer type is i32. Use usize for indexing into arrays and slices.

Rust has f32 (single precision) and f64 (double precision, default). Always prefer f64 unless you have a specific memory or precision reason to use f32.

bool is either true or false. char represents a single Unicode scalar value and is four bytes wide — it can hold emoji, CJK characters, and any other Unicode point.

fn main() {
let flag: bool = true;
let letter: char = 'R';
let emoji: char = '\u{1F980}'; // crab emoji
println!("flag={}, letter={}, emoji={}", flag, letter, emoji);
}

A tuple groups values of potentially different types into one compound value. It has a fixed length. Access individual elements with dot notation and the zero-based index.

fn main() {
let point: (i32, f64, bool) = (1, 2.5, false);
println!("{} {} {}", point.0, point.1, point.2);
// Destructuring a tuple
let (a, b, c) = point;
println!("a={}, b={}, c={}", a, b, c);
}

An array holds a fixed number of values of the same type. The type annotation is [T; N] where T is the element type and N is the length — both known at compile time. Use slices (&[T]) when you need a dynamically-sized view.

fn main() {
let arr: [i32; 4] = [10, 20, 30, 40];
println!("first={}, last={}, len={}", arr[0], arr[3], arr.len());
// Repeat initializer: [value; count]
let zeros = [0_i32; 5];
println!("zeros len = {}", zeros.len());
}

Rust’s type system is static — every value has a type known at compile time — but you rarely need to write it out. The compiler infers types from context. You only need an annotation when the inference is ambiguous.

fn main() {
let n = 42; // inferred as i32
let f = 1.5; // inferred as f64
let s = "hello"; // inferred as &str
// Suffix syntax forces a specific numeric type
let byte = 255_u8;
println!("{} {} {} {}", n, f, s, byte);
}
fn main() {
// Scalar types
let n: i32 = -42;
let f: f64 = 3.14;
let b: bool = true;
let c: char = 'R';
println!("i32: {}, f64: {}, bool: {}, char: {}", n, f, b, c);
// Tuple: fixed-length, mixed types
let tup: (i32, f64, bool) = (1, 2.5, false);
println!("tuple.0 = {}, tuple.1 = {}, tuple.2 = {}", tup.0, tup.1, tup.2);
// Array: fixed-length, same type
let arr: [i32; 4] = [10, 20, 30, 40];
println!("arr[0] = {}, arr[3] = {}, len = {}", arr[0], arr[3], arr.len());
// Type inference
let inferred = 99_u8;
println!("inferred u8: {}", inferred);
}
What is the default integer type when you write let x = 42?
How wide is a char value in Rust?
Which type annotation describes an array of five i32 values?
What does the suffix in 255_u8 communicate to the compiler?