变量与数据

原理

Rust 类型系统分为两类存储:栈(stack)和堆(heap)。

栈上数据大小在编译期确定,分配/释放是单指令栈指针移动(sub rsp, N / add rsp, N)。所有标量类型(i32, f64, bool, char)和其组合均存于栈,实现 Copy trait 后赋值行为是 memcpy

堆上数据大小在运行时可变(String, Vec<T>),由分配器(默认 jemalloc 或系统 malloc)管理。非 Copy 类型赋值触发所有权转移(move),即仅拷贝栈上的”胖指针”(ptr + len + cap),不深拷贝堆数据。

constlet 的区别:常量在编译期求值,直接内联到使用点(类似 C 的 #define),不占运行时内存地址。数组 [T; N] 的大小 N 也必须在编译期确定。

C: 变量与数据类型


语法

整数类型全表

类型位宽范围有符号
i88-128 ~ 127
i1616-32768 ~ 32767
i3232-21亿 ~ 21亿是(默认)
i6464-9e18 ~ 9e18
i128128极大
isize指针宽平台相关
u8/u16/u32/u64/u128/usize0 ~ 2^n-1
let a: i8 = 100;
let b: u8 = 200;
let idx: usize = 0;   // 数组索引用

浮点数

let pi: f64 = 3.14159;   // 默认 f64
let half: f32 = 0.5;
let e = 2.71828_f64;     // 后缀写法

布尔与字符

let ok: bool = true;
let c: char = '中';      // 4-byte Unicode

复合类型

// 元组:固定长度,类型可不同
let t: (i32, &str, f64) = (42, "hi", 3.14);
println!("{}", t.1);        // 索引访问
let (x, y, z) = t;          // 解构
 
// 数组:固定长度,同类型
let arr: [i32; 5] = [1, 2, 3, 4, 5];
let zeros = [0; 100];       // 100个0
println!("{}", arr[0]);
println!("{}", arr.len());

类型转换

let a: i32 = 42;
let b: i64 = a as i64;     // 安全扩展
let c: i8 = a as i8;       // 可能截断
let f: i32 = 3.14 as i32;  // 小数截断 → 3

Rust 不做隐式类型转换。跨类型必须通过 as

常量

const MAX: u32 = 1000;
const PI: f64 = 3.14159;
// 类型标注必须出现,值编译期确定
letconst
可变性默认不可变,可加 mut永远不可变
类型标注可选必须
求值时机运行时编译时

实践

力扣问题

力扣: 力扣简单计算题

fn main() {
    let a: i64 = read_one();
    let b: i64 = read_one();
    let c: i64 = read_one();
    println!("{}", (a + b) * c);
}

力扣: 力扣字符输出题

AI 自检

  1. let x = 3.14; 的默认类型为什么是 f64 而非 f32?从 CPU 角度解释。
  2. 元组 (1, String::from("hi"))Copy 类型吗?为什么?