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

rust高级特征

文章目录

  • 不安全的rust
    • 解引用裸指针
      • 裸指针与引用和智能指针的区别
      • 裸指针使用解引用运算符 *,这需要一个 unsafe 块
      • 调用不安全函数或方法
      • 在不安全的代码之上构建一个安全的抽象层
    • 使用 extern 函数调用外部代码
      • rust调用C语言函数
      • rust接口被C语言程序调用
    • 访问或修改可变静态变量
      • 静态变量
      • 可变静态变量
    • 实现不安全 trait
    • 访问联合体中的字段
  • 高级trait
    • 关联类型在 trait 定义中指定占位符类型
      • 使用关联类型:针对一个类型的实现
      • 使用泛型:针对多个类型的实现
  • 参考

不安全的rust

不安全的rust提供的能力如下:

  • 解引用裸指针
  • 调用不安全的函数或方法
  • 访问或修改可变静态变量
  • 实现不安全 trait
  • 访问 union 的字段

unsafe 并不会关闭借用检查器或禁用任何其他 Rust 安全检查:如果在不安全代码中使用引用,它仍会被检查。

unsafe 关键字只是提供了那五个不会被编译器检查内存安全的功能。你仍然能在不安全块中获得某种程度的安全。

解引用裸指针

裸指针与引用和智能指针的区别

  • 允许忽略借用规则,可以同时拥有不可变和可变的指针,或多个指向相同位置的可变指针
  • 不保证指向有效的内存
  • 允许为空
  • 不能实现任何自动清理功能

eg:如何从引用同时创建不可变和可变裸指针

#![allow(unused)]
fn main() {let mut num = 5;let r1 = &num as *const i32; //不可变裸指针let r2 = &mut num as *mut i32; //可变裸指针
}

裸指针使用解引用运算符 *,这需要一个 unsafe 块

#![allow(unused)]
fn main() {let mut num = 5;let r1 = &num as *const i32;let r2 = &mut num as *mut i32;unsafe {println!("r1 is: {}", *r1);println!("r2 is: {}", *r2);}
}

编译

▶ cargo runBlocking waiting for file lock on build directoryCompiling bobo v0.1.0 (/home/wangji/code/rust/bobo)Finished `dev` profile [unoptimized + debuginfo] target(s) in 9.83sRunning `target/debug/bobo`
r1 is: 5
r2 is: 5

调用不安全函数或方法

#![allow(unused)]
fn main() {unsafe fn dangerous() {}// 必须在一个单独的 unsafe 块中调用 dangerous 函数unsafe {dangerous();}
}

在不安全的代码之上构建一个安全的抽象层

问题代码

#![allow(unused)]
fn main() {let mut v = vec![1, 2, 3, 4, 5, 6];let r = &mut v[..];let (a, b) = r.split_at_mut(3);assert_eq!(a, &mut [1, 2, 3]);assert_eq!(b, &mut [4, 5, 6]);
}fn split_at_mut(slice: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) {let len = slice.len();assert!(mid <= len);// 不能对切片进行两次可变借用(&mut slice[..mid], &mut slice[mid..])
}

使用slice处理裸指针

#![allow(unused)]
fn main() {let mut v = vec![1, 2, 3, 4, 5, 6];let r = &mut v[..];let (a, b) = r.split_at_mut(3);assert_eq!(a, &mut [1, 2, 3]);assert_eq!(b, &mut [4, 5, 6]);
}use std::slice;
// 切片slice包括指向某个数据的指针和数据的长度
fn split_at_mut(slice: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) {let len = slice.len();let ptr = slice.as_mut_ptr(); // 返回指向slice中第一个元素的裸指针assert!(mid <= len);unsafe {(slice::from_raw_parts_mut(ptr, mid),slice::from_raw_parts_mut(ptr.add(mid), len - mid),)}
}

使用 extern 函数调用外部代码

extern,有助于创建和使用 外部函数接口(Foreign Function Interface, FFI)。外部函数接口是一个编程语言用以定义函数的方式,其允许不同(外部)编程语言调用这些函数。

如何集成 C 标准库中的 abs 函数。

rust调用C语言函数

extern "C" {fn abs(input: i32) -> i32;
}fn main() {unsafe {println!("Absolute value of -3 according to C: {}", abs(-3));}
}

rust接口被C语言程序调用

还需增加 #[no_mangle] 标注来告诉 Rust 编译器不要 mangle 此函数的名称。Mangling 发生于当编译器将我们指定的函数名修改为不同的名称时,这会增加用于其他编译过程的额外信息,不过会使其名称更难以阅读。

每一个编程语言的编译器都会以稍微不同的方式 mangle 函数名,所以为了使 Rust 函数能在其他语言中指定,必须禁用 Rust 编译器的 name mangling。

#![allow(unused)]
fn main() {#[no_mangle]pub extern "C" fn call_from_c() {println!("Just called a Rust function from C!");}
}

访问或修改可变静态变量

静态变量

rust中全局变量就是静态变量

static HELLO_WORLD: &str = "Hello, world!";fn main() {println!("name is: {}", HELLO_WORLD);
}

可变静态变量

访问不可变静态变量必须使用unsafe{}包起来

static mut COUNTER: u32 = 0;fn add_to_count(inc: u32) {unsafe {COUNTER += inc;}
}fn main() {add_to_count(3);unsafe {println!("COUNTER: {}", COUNTER);}
}

实现不安全 trait

#![allow(unused)]
fn main() {unsafe trait Foo {// methods go here}unsafe impl Foo for i32 {// method implementations go here}
}

访问联合体中的字段

高级trait

关联类型在 trait 定义中指定占位符类型

关联类型(associated types)是一个将类型占位符与 trait 相关联的方式,这样 trait 的方法签名中就可以使用这些占位符类型。trait 的实现者会针对特定的实现在这个类型的位置指定相应的具体类型。如此可以定义一个使用多种类型的 trait,直到实现此 trait 时都无需知道这些类型具体是什么。

使用关联类型:针对一个类型的实现

#![allow(unused)]
fn main() {}pub trait Iterator {//一个带有关联类型的 trait 的例子是标准库提供的 Iterator trait。它有一个叫做 Item 的关联类型来替代遍历的值的类型。type Item;fn next(&mut self) -> Option<Self::Item>;
}
struct Counter {}
impl Iterator for Counter {type Item = u32;fn next(&mut self) -> Option<Self::Item> {// --snip--Some(0)}
}// 报错!!
impl Iterator for Counter {type Item = u16;fn next(&mut self) -> Option<Self::Item> {// --snip--Some(0)}
}

使用泛型:针对多个类型的实现

使用泛型修改:可以支持多个类型

#![allow(unused)]
fn main() {}pub trait Iterator<T> {fn next(&mut self) -> Option<T>;
}
struct Counter {}
impl Iterator<u32> for Counter {fn next(&mut self) -> Option<u32> {// --snip--Some(0)}
}impl Iterator<u16> for Counter {fn next(&mut self) -> Option<u16> {// --snip--Some(0)}
}

参考

  • 第19章~编写不安全的Rust代码

  • 高级特征


http://www.mrgr.cn/news/71987.html

相关文章:

  • JavaScript总结
  • CSS多列布局:打破传统布局的束缚
  • 【MySQL】explain之type类型
  • git上feature合并到development分支
  • 【数据库】数据库设计
  • sql速度优化多条合并为一条语句
  • 基于微信小程序的养老院管理系统的设计与实现,LW+源码+讲解
  • Qt---双缓冲绘图
  • 【bat】自动生成指定层级文件夹
  • pytorch奇怪错误
  • 数字信号处理Python示例(12)生成Chirp(线性调频)信号
  • 实验27:lcd12864液晶显示实验
  • CAN总线位同步的使用以及总线仲裁规则详解
  • 基于YOLOv5的人群密度检测系统设计与实现
  • 跟着尚硅谷学vue2—进阶版2.0—使用 Vue 脚手架2.0
  • 常用数字器件的描述-时序逻辑器件的描述
  • 类似keepalived的软件还有哪些
  • Docker部署Redis哨兵
  • 在 Service Worker 中caches.put() 和 caches.add()/caches.addAll() 方法他们之间的区别
  • 【知识科普】ARM架构和x86架构
  • CustomersettleController
  • 大循环引起CPU负载过高
  • Android命令行启动SoftAP功能
  • golang项目三层依赖架构,自底向上;依赖注入trpc\grpc
  • 51c视觉~合集6
  • 【含文档】基于ssm+jsp的在线网课管理系统(含源码+数据库+lw)