众所周知,Rust语言的指针是一种安全的指针,它会遵循一定的规则,比如ownership规则,会确保不出现悬挂指针。但是当我们需要写一些底层框架的时候,往往需要绕过这些规则,自由的控制指针,这时候我们就可以使用原始指针
1、定义原始指针
我们可以通过以下方法定义原始指针:
fn main() {
let mut num = 5;
let r1 = &num as *const i32;
let r2 = &mut num as *mut i32;
}
通过&num获取的是Rust的不可修改(immutable)指针,然后通过as进行强制转换,转换为*const i32,表示不可修改(immutable)的i32类型的原始指针。
通过&mut 获取的是Rust的可修改(mutable)指针,然后通过as进行强制转换,转换为*mut i32,表示可修改(immutable)的i32类型的原始指针。
注意这里的*不是单独的操作符,而是应该把*const连起来看成是一个类型,同理*mut也是连起来作为单独的一个类型。
下面尝试对通过*const类型的指针进行内容修改:
fn main() {
let mut num = 5;
let r1 = &num as *const i32;
let r2 = &mut num as *mut i32;
unsafe {
*r1 = 1;
}
}
编译后会发现报错:
error[E0594]: cannot assign to `*r1`, which is behind a `*const` pointer
--> src/main.rs:9:10 |
6 | let r1 = &num as *const i32;
| ---- help: consider changing this to be a mutable pointer: `&mut num`
...
9 | *r1 = 1;
| ^^^^^^^ `r1` is a `*const` pointer, so the data it refers to cannot be written
这里编译器告诉我们,r1是个*const类型的原始指针,因此它指向的数据是不可以被修改的。
下面尝试使用可修改的原始指针进行数据修改:
fn main() {
let mut num = 5;
let r1 = &num as *const i32;
let r2 = &mut num as *mut i32;
unsafe {
*r2 = 1;
}
println!("num={:?}",num);
}
结果为
num=1
修改成功,说明*mut类型的原始指针是可以修改数据的。
2、获取原始指针指向的数据
我们可以通过操作符 * 来获取原始指针指向的数据:
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);
}
}
运行结果如下:
r1 is: 5
r2 is: 5
这里需要注意的是,定义原始指针可以直接在Rust语句中定义,获取原始指针指向的数据则需要在unsafe代码块中使用,否则编译会报错。