2、指针转换,传递和解引用
这儿用了windows里的一个常用的结构体RECT来做示范
LPRECT是RECT的*mut raw指针,也就是解引用后可以修改指向的数据的值,具体的说明见注释
use std::os::raw::{c_int,c_long};
//play应该是运行在*nix上的,所以用c_int代替c_long
#[derive(Debug)]
struct RECT{
x1:c_int,
y1:c_int,
x2:c_int,
y2:c_int,
}
//RECT可以看做两个POINT组成
#[derive(Debug)]
struct POINT{
x:c_int,
y:c_int,
}
//windows里常见的一个指针类型的声明方式
type LPRECT = *mut RECT;
fn use_rect(r:LPRECT){
//raw指针解引用的时候必须用unsafe
unsafe{
//注意解引用的时候需要把(*r)作为一个整体来对待
(*r).x1 = 10;
(*r).x2 = 100;
(*r).y1 = 20;
(*r).y2 = 200;
//打印也需要解引用
println!("{:?}",*r);
}
}
fn main() {
//这儿测试play运行的操作系统类型
let c:c_long = 5;
println!("size of c_long:{}",std::mem::size_of_val(&c));
//use_rect函数需要r的&mut借用,所以要声明成mut
let mut r = RECT{x1:1,y1:2,x2:1,y2:2};
println!("{:?}",r);
//raw指针也可以隐式转换,比如这么调用也是可以的:use_rect(&mut r);
//因为use_rect接受*mut raw指针,所以r必须是&mut借用
use_rect(&mut r as LPRECT);
//再次打印,看use_rect是否改变了r的值
println!("{:?}",r);
//下面是用POINT指针访问RECT内容,因为只需要打印所以只要获取*const就可以了
//首先获取RECT的raw pointer
let pr = &r as *const RECT;
//转换成POINT的raw pointer
let pp = pr as *const POINT;
unsafe{
//打印第一个POINT,就是 x1,y1
println!("{:?}",*pp);
//调用raw pointer的offset方法,打印第二个POINT,就是x2,y2
println!("{:?}",*pp.offset(1));
}
}
可以在Play运行通过:http://is.gd/mQgH6V
运行结果:
size of c_long:8
RECT { x1: 1, y1: 2, x2: 1, y2: 2 }
RECT { x1: 10, y1: 20, x2: 100, y2: 200 }
RECT { x1: 10, y1: 20, x2: 100, y2: 200 }
POINT { x: 10, y: 20 }
POINT { x: 100, y: 200 }
c_long的定义可以看:src/libstd/os/raw.rs
#[cfg(any(target_pointer_width = "32", windows))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_long = i32;
#[cfg(all(target_pointer_width = "64", not(windows)))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_long = i64;
参考链接:
https://doc.rust-lang.org/stable/book/raw-pointers.html
https://doc.rust-lang.org/stable/std/primitive.pointer.html