Primitive Type pointer [-] [+]
Operations on unsafe pointers, *const T
, and *mut T
.
Working with unsafe pointers in Rust is uncommon, typically limited to a few patterns.
Use the null
function to create null pointers, and the is_null
method
of the *const T
type to check for null. The *const T
type also defines
the offset
method, for pointer math.
Common ways to create unsafe pointers
1. Coerce a reference (&T
) or mutable reference (&mut T
).
fn main() {
let my_num: i32 = 10;
let my_num_ptr: *const i32 = &my_num;
let mut my_speed: i32 = 88;
let my_speed_ptr: *mut i32 = &mut my_speed;
}let my_num: i32 = 10; let my_num_ptr: *const i32 = &my_num; let mut my_speed: i32 = 88; let my_speed_ptr: *mut i32 = &mut my_speed;
To get a pointer to a boxed value, dereference the box:
fn main() { let my_num: Box<i32> = Box::new(10); let my_num_ptr: *const i32 = &*my_num; let mut my_speed: Box<i32> = Box::new(88); let my_speed_ptr: *mut i32 = &mut *my_speed; }let my_num: Box<i32> = Box::new(10); let my_num_ptr: *const i32 = &*my_num; let mut my_speed: Box<i32> = Box::new(88); let my_speed_ptr: *mut i32 = &mut *my_speed;
This does not take ownership of the original allocation and requires no resource management later, but you must not use the pointer after its lifetime.
2. Consume a box (Box<T>
).
The into_raw
function consumes a box and returns
the raw pointer. It doesn't destroy T
or deallocate any memory.
use std::boxed; unsafe { let my_speed: Box<i32> = Box::new(88); let my_speed: *mut i32 = boxed::into_raw(my_speed); // By taking ownership of the original `Box<T>` though // we are obligated to put it together later to be destroyed. drop(Box::from_raw(my_speed)); }
Note that here the call to drop
is for clarity - it indicates
that we are done with the given value and it should be destroyed.
3. Get it from C.
#![feature(libc)] extern crate libc; use std::mem; fn main() { unsafe { let my_num: *mut i32 = libc::malloc(mem::size_of::<i32>() as libc::size_t) as *mut i32; if my_num.is_null() { panic!("failed to allocate memory"); } libc::free(my_num as *mut libc::c_void); } }extern crate libc; use std::mem; fn main() { unsafe { let my_num: *mut i32 = libc::malloc(mem::size_of::<i32>() as libc::size_t) as *mut i32; if my_num.is_null() { panic!("failed to allocate memory"); } libc::free(my_num as *mut libc::c_void); } }
Usually you wouldn't literally use malloc
and free
from Rust,
but C APIs hand out a lot of pointers generally, so are a common source
of unsafe pointers in Rust.
Methods
impl<T> *const T where T: ?Sized
fn is_null(self) -> bool
Returns true if the pointer is null.
unsafe fn as_ref(&self) -> Option<&'a T>
: Option is not clearly the right return type, and we may want to tie the return lifetime to a borrow of the raw pointer
Returns None
if the pointer is null, or else returns a reference to
the value wrapped in Some
.
Safety
While this method and its mutable counterpart are useful for null-safety, it is important to note that this is still an unsafe operation because the returned value could be pointing to invalid memory.
unsafe fn offset(self, count: isize) -> *const T
Calculates the offset from a pointer. count
is in units of T; e.g. a
count
of 3 represents a pointer offset of 3 * sizeof::<T>()
bytes.
Safety
The offset must be in-bounds of the object, or one-byte-past-the-end.
Otherwise offset
invokes Undefined Behaviour, regardless of whether
the pointer is used.
impl<T> *mut T where T: ?Sized
fn is_null(self) -> bool
Returns true if the pointer is null.
unsafe fn as_ref(&self) -> Option<&'a T>
: Option is not clearly the right return type, and we may want to tie the return lifetime to a borrow of the raw pointer
Returns None
if the pointer is null, or else returns a reference to
the value wrapped in Some
.
Safety
While this method and its mutable counterpart are useful for null-safety, it is important to note that this is still an unsafe operation because the returned value could be pointing to invalid memory.
unsafe fn offset(self, count: isize) -> *mut T
Calculates the offset from a pointer. count
is in units of T; e.g. a
count
of 3 represents a pointer offset of 3 * sizeof::<T>()
bytes.
Safety
The offset must be in-bounds of the object, or one-byte-past-the-end.
Otherwise offset
invokes Undefined Behaviour, regardless of whether
the pointer is used.
unsafe fn as_mut(&self) -> Option<&'a mut T>
: return value does not necessarily convey all possible information
Returns None
if the pointer is null, or else returns a mutable
reference to the value wrapped in Some
.
Safety
As with as_ref
, this is unsafe because it cannot verify the validity
of the returned pointer.