Rust 数据类型

标量类型、复合类型、字符串的两种形态、以及 `as` 转换。

Beginner
Key Points`String` 是可增长的所有权字符串,`&str` 是借用的字符串切片。

标量类型

TypeSizeRange / Note
i8 / u81 字节-128~127 / 0~255
i32 / u324 字节默认整数类型是 i32
i64 / u648 字节时间戳、ID
i128 / u12816 字节大整数
isize / usize指针宽度索引、长度
f32 / f644 / 8 字节默认浮点是 f64
bool1 字节true / false
char4 字节一个 Unicode 标量值
Rust
fn main() {
    let i = 42;              // i32
    let u: u8 = 255;
    let f = 3.14;            // f64
    let b = true;
    let c = '中';
    let emoji = '🦀';

    println!("{} {} {} {} {} {}", i, u, f, b, c, emoji);
}
Output
42 255 3.14 true 中 🦀

char is a 4-byte Unicode scalar and can hold an emoji, unlike C's 1-byte char. Rust strings are not char arrays.

元组与数组

Rust
fn main() {
    // 元组:可以不同类型,定长
    let t: (i32, f64, char) = (1, 2.5, 'a');
    let (x, y, z) = t;              // 解构
    println!("{} {} {}", x, y, z);
    println!("{}", t.0);            // 下标访问

    // 数组:同类型,定长,栈上分配
    let arr = [1, 2, 3, 4, 5];
    let zeros = [0; 5];             // 5 个 0
    println!("{} {}", arr[0], arr.len());
    println!("{:?}", zeros);

    // 遍历
    for v in arr {
        print!("{} ", v);
    }
    println!();
}
Output
1 2.5 a
1
1 5
[0, 0, 0, 0, 0]
1 2 3 4 5 

Array length is part of the type: [i32; 3] and [i32; 4] differ. Use Vec<T> day to day; arrays only for fixed small lengths.

String 与 &str

Rust
fn main() {
    // &str:字符串字面量,不可变,借用
    let s1: &str = "hello";

    // String:堆上分配,可增长,拥有所有权
    let mut s2 = String::from("hello");
    s2.push_str(", world");
    s2.push('!');

    println!("{} | {}", s1, s2);
    println!("{} {}", s1.len(), s2.len());

    // String → &str
    let slice: &str = &s2;
    println!("{}", slice);

    // &str → String
    let owned: String = s1.to_string();
    println!("{}", owned);
}
Output
hello | hello, world!
5 13
hello, world!
hello
TypeOwnsGrowableTypical use
&str否(借用)否函数参数、字面量
String是是需要持有或修改的文本
Prefer &str over String in parameters: &str accepts both &String and literals, while String forces the caller to clone. This is standard Rust advice.

类型转换

Rust
fn main() {
    let a = 3.99_f64;
    println!("{}", a as i32);       // 3,向零截断

    let b = 300_i32;
    println!("{}", b as u8);        // 44,截断低 8 位

    let c = 65_u8;
    println!("{}", c as char);      // A

    // 字符串解析
    let n: i32 = "42".parse().unwrap();
    println!("{}", n + 1);
}
Output
3
44
A
43
as does not check: 300_i32 as u8 silently truncates to 44 and -1_i32 as u32 becomes 4294967295. For external data use TryFrom/try_into(), which return Result.
Rust
use std::convert::TryInto;

let big: i64 = 300;
let small: Result<u8, _> = big.try_into();
println!("{:?}", small);        // Err(PosOverflow(300))
Output
Err(PosOverflow(300))

Friends & Partners