当前位置: 首页 > news >正文

Rust 中 i32 与 *i32 的深度解析

Rust 中 &i32*i32 的深度解析

在 Rust 中,&i32*i32 是两种完全不同的指针类型,它们在安全性、所有权和使用方式上有本质区别。以下是详细对比:

核心区别概览

指针类型
引用 &i32
裸指针 *i32
安全
编译器检查
生命周期管理
不安全
手动管理
FFI/底层操作

详细对比分析

1. &i32 - 引用(安全指针)

特性说明
安全性100% 安全,编译器保证有效性
所有权借用检查器控制,不转移所有权
解引用自动解引用(Deref coercion)
使用场景日常 Rust 编程
可变性&i32(不可变)或 &mut i32(可变)
空值永远不为空
别名规则严格遵循借用规则(要么多个不可变引用,要么一个可变引用)
fn safe_ref_example() {let num = 42;let ref_num: &i32 = # // 创建不可变引用// 自动解引用println!("Value: {}", *ref_num); println!("Value: {}", ref_num); // 同样有效// 编译错误:不能同时存在可变和不可变引用// let mut_ref = &mut num;
}

2. *i32 - 裸指针(不安全指针)

特性说明
安全性不安全,需要 unsafe 块操作
所有权无所有权概念,可能悬垂
解引用必须显式解引用(在 unsafe 中)
使用场景FFI、底层系统编程、性能优化
可变性*const i32(不可变)或 *mut i32(可变)
空值可能为空(std::ptr::null()
别名规则无编译时检查,需手动保证安全
fn raw_ptr_example() {let num = 42;let raw_ptr: *const i32 = &num as *const i32;// 必须使用 unsafe 块解引用unsafe {println!("Value: {}", *raw_ptr);}// 可能创建悬垂指针let dangling_ptr: *const i32;{let temp = 100;dangling_ptr = &temp as *const i32;} // temp 离开作用域// 危险:dangling_ptr 现在无效!
}

关键区别详解

1. 安全机制对比

操作
&i32
*i32
编译时检查
借用规则
生命周期验证
运行时风险
悬垂指针
数据竞争

2. 内存访问对比

操作&i32*i32
创建引用/指针&value&value as *const i32
解引用自动或显式 *ref必须 unsafe { *ptr }
空指针不可能std::ptr::null()
指针算术不支持支持(ptr.offset(1)
类型转换有限制(通过 trait)自由转换(as *mut u8

3. 典型使用场景

&i32 场景:
// 函数参数传递
fn print_value(v: &i32) {println!("Value: {}", v);
}// 结构体借用
struct Processor<'a> {data: &'a i32,
}// 迭代器使用
let sum: i32 = vec![1, 2, 3].iter().map(|&x| x * 2).sum();
*i32 场景:
// C 语言交互
extern "C" {fn c_function(ptr: *mut i32);
}// 自定义内存管理
unsafe fn allocate_buffer(size: usize) -> *mut u8 {let layout = std::alloc::Layout::array::<u8>(size).unwrap();std::alloc::alloc(layout)
}// 高性能算法
unsafe fn fast_sum(ptr: *const i32, len: usize) -> i32 {let mut sum = 0;for i in 0..len {sum += *ptr.add(i);}sum
}

转换关系

1. 安全转换

// 引用 → 裸指针(安全)
let num = 42;
let ref_num: &i32 = &num;
let raw_ptr: *const i32 = ref_num as *const i32;

2. 不安全转换

// 裸指针 → 引用(不安全)
unsafe {let ref_back: &i32 = &*raw_ptr;
}

3. 转换注意事项

as *const
unsafe &*
as *const
FFI
Rust调用
安全世界
裸指针
引用
C语言

最佳实践指南

何时使用 &i32

  1. 99% 的日常 Rust 编程
  2. 函数参数传递
  3. 结构体字段借用
  4. 实现 trait 对象 (&dyn Trait)

何时使用 *i32

  1. 与 C 库交互(FFI)
  2. 实现底层数据结构(如自定义分配器)
  3. 极端性能优化场景
  4. 操作系统内核开发

安全使用裸指针的模式:

// 模式1:封装在安全API中
struct SafePointer {ptr: *mut i32,len: usize,
}impl SafePointer {// 安全构造函数pub fn new(data: &mut [i32]) -> Self {SafePointer {ptr: data.as_mut_ptr(),len: data.len(),}}// 安全访问方法pub fn get(&self, index: usize) -> Option<&i32> {if index < self.len {unsafe { Some(&*self.ptr.add(index)) }} else {None}}
}// 模式2:与生命周期绑定
struct GuardedPtr<'a> {ptr: *const i32,_marker: std::marker::PhantomData<&'a i32>,
}impl<'a> GuardedPtr<'a> {pub fn new(reference: &'a i32) -> Self {GuardedPtr {ptr: reference as *const i32,_marker: std::marker::PhantomData,}}pub fn get(&self) -> &'a i32 {unsafe { &*self.ptr }}
}

性能对比

操作&i32*i32
创建开销零成本抽象零成本
解引用开销等同直接访问等同直接访问
安全检查开销编译时(零运行时开销)无检查(需手动验证)
优化潜力编译器充分优化同左,但需更多人工干预

常见错误示例

错误1:悬垂引用

fn dangling_ref() -> &'static i32 {let x = 42;&x // 错误:返回局部变量引用
}

错误2:不安全裸指针使用

fn unsafe_ptr_demo() {let ptr: *const i32;{let value = 100;ptr = &value;} // value 被丢弃unsafe {println!("{}", *ptr); // 未定义行为!}
}

错误3:违反别名规则

fn alias_violation() {let mut data = 42;let ref1 = &data;let ref2 = &mut data; // 错误:同时存在可变和不可变引用println!("{}", ref1);
}

总结对比表

特性&i32*const i32*mut i32
安全性安全不安全不安全
空值不可能可能可能
可变性不可变不可变可变
别名检查严格
生命周期编译器验证无保证无保证
使用场景常规编程FFI/只读访问FFI/写访问
解引用安全unsafeunsafe
自动转换支持 Deref不支持不支持

在 Rust 开发中,优先使用引用 &i32,只有在必要时(如 FFI 或底层系统编程)才使用裸指针 *i32,并且始终将其封装在安全的抽象中。

http://www.lryc.cn/news/621590.html

相关文章:

  • Java-JVM的内存模型
  • 网上商城|基于SprinBoot+vue的分布式架构网上商城系统(源码+数据库+文档)
  • 【学习笔记】进程、线程、协程及进程间通信
  • 电脑开机几秒后就停止然后再循环是怎么回事
  • 深入理解 Python 闭包:从原理到实践
  • 永磁同步电机控制 第二篇、电机的分类
  • web学习笔记6
  • 使用原生css实现word目录样式,标题后面的...动态长度并始终在标题后方(生成点线)
  • 硬件开发_基于STM32单片机的热水壶系统
  • 数据结构初阶:排序算法(一)插入排序、选择排序
  • 宋红康 JVM 笔记 Day02|JVM的架构模型、生命周期、发展历程
  • 46.Sentinel规则持久化
  • mlir clone
  • week1-[循环嵌套]画正方形
  • cloudflare缓存配置
  • AAAI爆款:目标检测新范式,模块化设计封神之作
  • StarRocks数据库集群的完整部署流程
  • JavaScript性能优化30招
  • 【车联网kafka】常用参数及其命令总结(第八篇)
  • 计算机网络:(十五)TCP拥塞控制与TCP拥塞控制算法
  • es7.x的客户端连接api以及Respository与template的区别
  • Notepad++插件开发实战指南
  • 【详细操作指南】如何将 Moodle 与编辑器连接,以修改文档、检查和批改作业等
  • HTTP/2新型漏洞“MadeYouReset“曝光:可发动大规模DoS攻击
  • HTTP 请求方法:GET 与 POST
  • STM32L051 RTC闹钟配置详解
  • 《JMeter核心技术、性能测试与性能分析》 教学大纲及标准
  • 硬核实用!R+贝叶斯解决真实问题:参数估计(含可靠性分析) + 回归建模(含贝叶斯因子比较) + 生产级计算实践 赠「常见报错解决方案」秘籍!
  • 电商架构测试体系:ZKmall开源商城筑牢高并发场景下的系统防线
  • Jmeter自定义脚本