as Casting / Numeric Type Conversion
To cast between primitive types in Rust, use the as keyword. You can convert between integer, floating-point, and pointer types. Because Rust does not perform implicit type conversions, explicit casts are required.
Syntax
// Cast between integers let x: i32 = 42; let y: i64 = x as i64; // small → large (safe) let z: i8 = x as i8; // large → small (truncation) // Integer ↔ floating-point let f: f64 = 3.99; let n: i32 = f as i32; // fractional part is truncated (3) let f2: f64 = n as f64; // integer converted to floating-point // Signed ↔ unsigned let u: u8 = 200; let s: i8 = u as i8; // bit pattern preserved (-56) // Conversion to usize / isize let idx: usize = 5usize; let val: i32 = idx as i32; // char ↔ u32 let c: char = 'A'; let n: u32 = c as u32; // 65 let c2: char = char::from(65u8); // 'A'
Cast behavior reference
| Conversion | Behavior |
|---|---|
| Smaller integer type → larger integer type | Sign-extended (signed) or zero-extended (unsigned). |
| Larger integer type → smaller integer type | High-order bits are truncated (wrapping behavior). |
| f64/f32 → integer type | Fractional part is truncated. Out-of-range values are saturated (Rust 1.45 and later). |
| Integer type → f64/f32 | Converted to the nearest approximation. Precision may be lost. |
| Signed → unsigned | Bit pattern is preserved. Negative values become large positive numbers. |
| Safe cast alternatives | Use TryFrom for checked conversions that return a Result. |
Sample code
fn main() {
// Widening cast (safe)
let small: i32 = 1000;
let large: i64 = small as i64;
println!("i32 → i64: {}", large); // 1000
// Truncating cast (high-order bits discarded)
let big: i32 = 300;
let byte: u8 = big as u8; // 300 % 256 = 44
println!("300 as u8: {}", byte); // 44
// Negative number cast to unsigned
let neg: i32 = -1;
let u: u32 = neg as u32; // bit pattern preserved
println!("-1 as u32: {}", u); // 4294967295
// f64 → integer (truncation toward zero)
let f = 3.99_f64;
let n = f as i32;
println!("3.99 as i32: {}", n); // 3 (truncated)
let f2 = -3.99_f64;
let n2 = f2 as i32;
println!("-3.99 as i32: {}", n2); // -3 (truncated toward zero)
// Out-of-range f64 → i32 (saturated in Rust 1.45 and later)
let big_f = 1_000_000.0_f64;
let clamped = big_f as i8; // saturates to i8 max value of 127
println!("1000000.0 as i8: {}", clamped); // 127
// char → numeric value
let c = 'A';
let code = c as u32;
println!("'A' as u32: {}", code); // 65
// Safe cast using TryFrom
use std::convert::TryFrom;
let big_num: i64 = 1000;
match i8::try_from(big_num) {
Ok(n) => println!("Conversion succeeded: {}", n),
Err(e) => println!("Conversion failed: {}", e), // out of range
}
// usize usage (e.g., array indexing)
let idx: i32 = 2;
let arr = [10, 20, 30, 40, 50];
println!("arr[{}] = {}", idx, arr[idx as usize]); // 30
}
Overview
Rust's as cast requires explicit casts, which prevents unintended type conversions. However, as never fails. When converting from a larger type to a smaller type, truncation occurs, so you should verify that the result is the value you intended.
For safe conversions, use the TryFrom trait and the try_from() method. A successful conversion returns Ok(value), and a failed conversion returns Err(error).
Note: Conversion from f64/f32 to an integer truncates toward zero, not rounds. For details on type conversion traits, see From / Into / TryFrom / TryInto traits.
If you find any errors or copyright issues, please contact us.