2.5 Data Types and Type Annotations
Rust requires every variable to have a definite type, either inferred by the compiler or explicitly specified. Once a variable is assigned a type, it cannot change throughout its lifetime. This ensures type safety while preventing unintended type mismatches.
2.5.1 Basic Data Types
- Integers:
i8
,i16
,i32
,i64
,i128
,isize
(signed) andu8
,u16
,u32
,u64
,u128
,usize
(unsigned) - Floating-Point:
f32
,f64
- Boolean:
bool
- Character:
char
(4 bytes, supporting Unicode scalar values)
Integer and floating-point data types include their bit width in the type name (for example, u8
is an 8-bit unsigned integer).
usize
and isize
scale with the target platform’s pointer size (similar to size_t
or ptrdiff_t
in C/C++). Rust’s char
represents a Unicode scalar value, unlike C’s single-byte char
.
2.5.2 Type Inference
Rust can infer types based on usage:
fn main() { let x = 42; // i32 inferred let y = 3.14; // f64 inferred println!("x = {}, y = {}", x, y); }
2.5.3 Explicit Type Annotation
When inference is unclear, or you need a different default, specify the type:
fn main() { let x: u8 = 255; println!("x = {}", x); }
2.5.4 Comparison with C
In C, int x = 42;
typically yields a 32-bit integer, though the size can vary by platform. C99 introduced stdint.h
for fixed-width types (for example, int32_t
), similar to Rust’s explicit-width types.