Skip to content

原生数据类型

Rust 是静态类型语言,编译时就必须知道所有变量的类型。根据值及其使用方式,Rust 编译器通常能自动推导出变量的类型。

Rust 有两种原生数据类型: 标量(scalar)类型复合(compound)类型

除了标量类型(如 i32f64charbool)和复合类型(元组、数组)这些原生类型外,复杂的数据结构几乎都由 structenum 构成。

标量类型

标量类型包括: 整型浮点型布尔类型字符类型

整型

语法: u/i + 位数

rust
let a: u8 = 1;
let b: i32 = -2;
  • u 无符号整数: 范围 02^n - 1
  • i 有符号整数: 范围 -2^(n-1)2^(n-1) - 1
无符号整数有符号整数长度范围
u8i88-bitu8:0-255 i8:-128-127
u16i1616-bitu16:0-65,535 i16:-32,768-32,767
u32i32(默认)32-bitu32:0-约 42.9 亿 i32:约 -21.4 亿-21.4 亿
u64i6464-bitu64:0-1.84 x 10^19 i64:-9.22 x 10^18-9.22 x 10^18
u128i128128-bit
usizeisize架构相关
  • u 代表 Unsigned,特指 Unsigned Integer (无符号整数),只能表示非负数(0 和正数)。
  • i 代表 Integer ,特指 Signed Integer (有符号整数),可以表示正数、负数和零。
  • usize/isize 的大小取决于目标平台的指针宽度: 32位系统为4字节(i32/u32),64位系统为8字节(i64/u64)。

1.整型字面值

0b 表示二进制、0o 表示八进制、0x 表示十六进制,默认是十进制。

数字字面值例子
Binary (二进制)let d: i32 = 0b1111_0000;
Octal (八进制)let c: i32 = 0o77;
Decimal (十进制)let a: i32 = 98_222;
Hex (十六进制)let b: i32 = 0xff;
Byte (单字节字符,仅限于u8)let e: u8 = b'A';

2._ 分隔数字

使用 _ 分隔数字可以提高可读性,编译器会忽略它们:

rust
let million = 1_000_000; // 等价于 let million = 1000000;
let hex = 0xFF_FF;       // 等价于 let hex = 0xFFFF;

3.字面量后缀类型标注

rust
let a = 10u8;      // 等于 let a: u8 = 10;
let b = 20i64;     // 等于 let b: i64 = 20;
let c = 3.14_f32;  // 等于 let c: f32 = 3.14;
let d = 30_isize;  // 等于 let d: isize = 30;

4.整数溢出

每种数值类型都有所能存储的最大数值和最小数值。当超出类型的有效范围时,Rust将报错(panic)。

rust
let x: u8 = 255; // x = 255 是 u8 的最大值
let y = x + 1;   // ❌ Debug 模式: panic!("attempt to add with overflow")

Debug模式 会 panic; Release模式 会变成 0

浮点型

语法: f + 位数

rust
let a: f32 = 3.14;
let b: f64 = 2.71828;
类型长度精度范围
f3232-bit 单精度浮点数约 6 ~ 9 位-1.18*10^38-3.40*10^38
f64(默认)64-bit 双精度浮点数约 15 ~ 17 位-2.23*10^308-1.79*10^308
  • f32: 占用 32 位(4 字节)。
  • f64: 占用 64 位(8 字节),正好是 f32 的两倍。

如果你计算圆周率,f32 可能只能精确到 3.141592,而 f64 能到 3.141592653589793

布尔类型 bool

  • truefalse 是仅有的两个值
  • 占 1 字节(8 bit)
rust
let t = true;
let f: bool = false;

if true { }     // ✅
if 1 { }        // ❌ 不允许,整数不能作为布尔条件;Rust 不会将整数隐式转换为 bool
if 1 != 0 { }   // ✅ 需要显式比较
  • 布尔值可以通过比较运算符(==<>等)生成
  • 布尔值可以通过逻辑运算符(&&||!)组合
rust
let a = 5;
let b = a > 3 && a < 10; // b = true

字符类型 char

char 类型是Rust中最原始的字符类型

  • 是一个 Unicode 标量值(Unicode scalar value)
  • 占 4 字节(32 bit)
  • 使用单引号 '' 声明
rust
let z: char = 'ℤ';  // 使用显式类型注释
let a = 'A';        // 1 字节表示,但占 4 字节内存
let emoji = '😻';  // 也是 4 字节

复合类型

复合类型是将多个不同类型的值组合成一个类型的主要方式

Rust 有两个原生的复合类型: 元组(tuple)数组(array)

元组 tuple

  • 定义语法: let 变量 = (类型1, 类型2, ...)
  • 取值语法: 变量.索引 或 模式匹配
rust
let tup: (i32, f64, u8) = (500, 6.4, 1);  // 元组类型注释
let (x, y, z) = tup;                      // 模式匹配取值
let first = tup.0;                        // 点号(.)取值
let second = tup.3;                       // ❌ 索引越界,编译错误

let mut tup1 = (1, 2, 3);                 // 定义一个可变元组
tup1.0 = 10;                              // ✅ 可以改变元组值
特性说明
大小一旦定义,元组的长度是固定的
类型元组中的每个元素可以是不同类型
所有权元组每个元素的所有权是独立的

本质是一个没有名字的匿名结构体

空元组

空元组也称为"单元类型"(unit type),使用 () 表示,等价于 JavaScript 的 undefined,很多表达式和函数默认返回它。

rust
let unit: () = ();

数组 array

  • 定义语法: let 变量 = [类型; 长度]
  • 取值语法: 变量[索引] 或 模式匹配
rust
let a = [1, 2, 3, 4, 5];            // 类型和长度由编译器推导
let a: [i32; 5] = [1, 2, 3, 4, 5];  // 显式类型注释,长度必须与元素数量匹配
let a = [3; 5];                     // 等于 let a = [3, 3, 3, 3, 3];

let first = a[0];                   // [] 取值
let second = a[5];                  // ❌ 索引越界,编译错误

let mut a = [1, 2, 3];              // 定义一个可变数组
a[0] = 10;                          // ✅ 可以改变元素值
特性说明
大小一旦定义,数组长度是固定的
类型数组中的每个元素的类型必须相同
所有权数组的所有权是整体的

usize 和 isize

usizeisize 是 Rust 中的特殊整数类型,在 内存和指针 章节中会再介绍。

usizeisize 的大小取决于目标平台的指针宽度:

  • 32位系统为4字节, 即 i32u32
  • 64位系统为8字节, 即 i64u64

使用场景:

  • usize数组索引和集合长度的标准类型(len()[] 索引均返回/接受 usize)。
  • isize 常用于指针偏移量计算(负偏移时派上用场)。

as 基本类型转换

Rust 不会自动进行类型转换,需要使用 as 关键字显式转换。截断和溢出行为由目标类型决定:

rust
// 数值类型转换
let a = 42i32 as f64;      // i32 → f64
let b = 3.99f64 as i32;    // f64 → i32,截断小数部分 → 3(不四舍五入)
let c = 300u32 as u8;      // 超出范围时截断(300 % 256 = 44)

// bool类型转换
let d = true as u8;        // bool → u8, true → 1, false → 0
let e = 0u8 as bool;       // u8 → bool, 0 → false, 非0 → true

// char类型相关转换
let f = 'A' as u32;        // char → u32(Unicode 码位: 65)
let g = 65u8 as char;      // u8 → char → 'A'

as 只能用于基本数值类型和 char/指针之间的转换,不能用于 String/&str 等复杂类型(需用 .to_string()/.parse() 等方法)。

整数溢出的安全处理方法

除了 Debug 模式 panic / Release 模式截断外,标准库提供了四组安全方法:

方法行为描述适用场景
checked_add()安全加法,溢出时返回 None需要明确处理溢出情况
saturating_add()饱和加法,溢出时结果固定在该类型的最大值或最小值需要边界保护
wrapping_add()环绕加法,溢出时按二进制环绕处理,行为与 Release 模式一致需要循环计数
overflowing_add()返回元组 (result, is_overflow),同时获得结果和溢出标志需要记录溢出事件

使用建议: 根据具体需求选择合适的方法,优先考虑 checked_add() 以获得更好的错误处理能力。

rust
let x: u8 = 255;
x.checked_add(1)      // → None(溢出返回 None)
x.saturating_add(1)   // → 255(饱和: 钉在最大/最小值)
x.wrapping_add(1)     // → 0(环绕: 和 Release 行为一致)
x.overflowing_add(1)  // → (0, true)(返回结果和是否溢出的元组)

基于 MIT 协议发布