从C到Rust:Trait From Into 类型转换

From / Into ------ 类型间的转换

一、这些 Trait 定义了数据的什么行为

rust 复制代码
pub trait From<T> {

fn from(value: T) -> Self;

}

  


pub trait Into<T> {

fn into(self) -> T;

}

From 的含义:"我可以从 T 转换而来。"

Into 的含义:"我可以转换到 T 去。"

两者是彼此的镜像:

rust 复制代码
// 实现 From 自动提供 Into(标准库的 blanket impl)

impl<T, U> Into<U> for T where U: From<T> {

fn into(self) -> U {

U::from(self)

}

}

所以通常只需要实现 From

rust 复制代码
impl From<i32> for MyType {

fn from(value: i32) -> Self {

MyType(value)

}

}

  


// 自动获得:

// let x: MyType = 42.into(); // Into<MyType> for i32

二、C 中是什么

2.1 C 的强制类型转换

c 复制代码
// C 的隐式转换------编译器自动执行

int x = 42;

double y = x; // int → double(隐式)

long z = x; // int → long(隐式)

  


// C 的显式转换(cast)------程序员写出来

double d = 3.14;

int i = (int)d; // double → int(截断)

  


// C 的指针转换------完全类型不安全

struct Point { int x, y; };

struct User { char name[32]; };

  


struct Point p = {1, 2};

struct User* u = (struct User*)&p; // ❌ 编译通过!但完全没有意义

2.2 C 的自定义转换函数

c 复制代码
// C 中"类型转换"就是命名函数------没有统一接口

struct string from_cstr(const char* s); // char* → string

struct string from_int(int n); // int → string

char* to_cstr(const struct string* s); // string → char*

  


// 每个库命名不同:

// mylib_from_int, theirlib_int_to_string, ...

三、C 的问题

3.1 隐式转换掩盖 bug

c 复制代码
// 最经典的 C 隐式转换 bug

double result = 5 / 2; // ❌ 2.0,不是 2.5

// 5 / 2 是整数除法,结果是 2(int)

// 然后隐式转为 double 2.0

  


// 本意是:

double result = 5.0 / 2; // 2.5

3.2 强制转换不安全

c 复制代码
// C 的 cast 可以绕过所有类型检查

int* ip = malloc(sizeof(int));

char* cp = (char*)ip; // ❌ 可以,但通常没有意义

  


void* vp = ip; // ✅ 隐式 void* 转换

int* ip2 = vp; // ✅ void* → int*(C 中隐式,C++ 需要 cast)

  


// 没有任何机制阻止你写出荒谬的转换

struct Socket {

int fd;

};

struct Database {

char* host;

int port;

};

struct Socket s = { 42 };

struct Database* db = (struct Database*)&s; // ❌ 编译通过!运行时崩溃

3.3 没有统一的转换接口

c 复制代码
// C 的"转换成字符串"有无数种命名

// itoa(n, buf, 10) ------ 非标准

// sprintf(buf, "%d", n) ------ 标准但笨重

// snprintf(buf, sz, "%d", n) ------ 安全版

// asprintf(&buf, "%d", n) ------ GNU 扩展

// 没有统一的 "to_string(n)" 接口

四、Rust 为什么需要这些 Trait

4.1 类型安全的转换------不是所有转换都被允许

rust 复制代码
// Rust 中不能随便转换类型

let x: i32 = 42;

// let y: f64 = x; // ❌ 编译错误!不能隐式转换

let y: f64 = x as f64; // ✅ 显式 as------你要的

let y: f64 = f64::from(x); // ✅ From------也是显式的

两个类型之间有没有 From 实现,由标准库作者或类型作者决定。 不是所有转换都合理。

4.2 常用 From 实现

rust 复制代码
// 标准库中的 From 实现

let s = String::from("hello"); // &str → String

let s = String::from(&my_string); // &String → String

  


// 数值类型间的 From

// i32 → i64 是安全的(不会丢失精度)

let x: i64 = i64::from(42i32); // ✅

  


// i64 → i32 不是安全的(可能溢出)

// let x: i32 = i32::from(42i64); // ❌ 没有这个 From!

// 需要用 TryFrom(下一章)

  


// 错误类型的转换

let err = std::io::Error::from(kind); // ErrorKind → Error

let err = String::from("error"); // &str → String

4.3 into() 的便利性------类型推导

rust 复制代码
// into() 利用类型推导------上下文决定目标类型

fn takes_string(s: String) {}

  


// 几种写法:

takes_string("hello".to_string());

takes_string(String::from("hello"));

takes_string("hello".into()); // ✅ 编译器推导出目标类型是 String

4.4 From 作为泛型约束

rust 复制代码
// 泛型函数:接受"任何可以从 &str 转换的类型"

fn parse<T: From<&str>>(s: &str) -> T {

T::from(s)

}

  


let x: String = parse("hello"); // ✅

// let y: i32 = parse("42"); // ❌ i32 没有 From<&str>

  


// 另一个例子:接受"任何可以转换为 String 的类型"

fn concat<T: Into<String>>(items: &[T]) -> String {

items.iter().map(|x| x.into()).collect::<Vec<_>>().join(", ")

}

4.5 自定义 From------实现类型安全转换

rust 复制代码
struct Point {

x: f64,

y: f64,

}

  


// 从整数元组转换

impl From<(i32, i32)> for Point {

fn from((x, y): (i32, i32)) -> Self {

Point {

x: x as f64,

y: y as f64,

}

}

}

  


// 从浮点元组转换

impl From<(f64, f64)> for Point {

fn from((x, y): (f64, f64)) -> Self {

Point { x, y }

}

}

  


let p1 = Point::from((1, 2)); // 使用 From

let p2: Point = (3.0, 4.0).into(); // 使用 Into

五、对比

维度 C 强制转换 Rust From / Into
安全性 无------任何类型都能 cast 到任何类型 有------只允许显式实现的转换
发现方式 靠文档和惯例 编译器知道------有 From 才能转换
错误处理 不适用(截断、丢失精度) 无(From 不失败)
泛型支持 T: From<U> 约束
隐式/显式 C 中隐式 + 显式 (cast) 总是显式(from() / into()
一致性 各库命名不同 统一的 From / Into

一句话总结 :C 的强制转换 (int)x 可以让任何类型变成任何其他类型------编译器不阻止,后果由程序员承担。Rust 的 From / Into 建立了类型间转换的白名单 ------只有实现者明确允许的转换才能发生,且调用方式统一(Type::from(x) / x.into())。

相关推荐
doiito8 小时前
【RUST AI】把 TTS 搬进浏览器:kokoroi-rs 的 WASM 实践
ai·rust·架构设计
jinshw9 小时前
自己实现GIS配图软件(一)
rust·开源·gis
程序员爱钓鱼9 小时前
Rust 元组 Tuple 详解:组合不同类型的数据
前端·后端·rust
humbinal1 天前
同时支持 gui & cli 的 parquet 文件查看工具,高性能小清新!
hive·python·rust·spark·开源·github·parquet
belowfrog1 天前
Rust 的 Deref 到底为啥这么乱呀!
rust
程序员爱钓鱼1 天前
Rust 数组 Array 详解:定义、访问、遍历与切片
后端·rust
程序员爱钓鱼2 天前
Rust if let 与 while let 详解:简化模式匹配
前端·后端·rust
第一程序员3 天前
Rust trait 入门:把 AI 客户端抽象成可替换接口
python·rust·github
分布式存储与RustFS3 天前
RustFS Beta.10 性能解读:PUT 全面反超 MinIO,Rust 重写对象存储成了?
开发语言·后端·rust