Primitive Type pointer
Expand description
Raw, unsafe pointers, *const T
, and *mut T
.
Working with raw pointers in Rust is uncommon, typically limited to a few patterns. Raw pointers
can be out-of-bounds, unaligned, or null
. However, when loading from or storing to a raw
pointer, it must be valid for the given access and aligned. When using a field expression,
tuple index expression, or array/slice index expression on a raw pointer, it follows the rules
of in-bounds pointer arithmetic.
Storing through a raw pointer using *ptr = data
calls drop
on the old value, so
write
must be used if the type has drop glue and memory is not already
initialized - otherwise drop
would be called on the uninitialized memory.
Use the null
and null_mut
functions to create null pointers, and the
is_null
method of the *const T
and *mut T
types to check for null.
The *const T
and *mut T
types also define the offset
method, for
pointer math.
§Common ways to create raw pointers
§1. Coerce a reference (&T
) or mutable reference (&mut T
).
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:
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.
let my_speed: Box<i32> = Box::new(88);
let my_speed: *mut i32 = Box::into_raw(my_speed);
// By taking ownership of the original `Box<T>` though
// we are obligated to put it together later to be destroyed.
unsafe {
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. Create it using &raw
Instead of coercing a reference to a raw pointer, you can use the raw borrow
operators &raw const
(for *const T
) and &raw mut
(for *mut T
).
These operators allow you to create raw pointers to fields to which you cannot
create a reference (without causing undefined behavior), such as an
unaligned field. This might be necessary if packed structs or uninitialized
memory is involved.
#[derive(Debug, Default, Copy, Clone)]
#[repr(C, packed)]
struct S {
aligned: u8,
unaligned: u32,
}
let s = S::default();
let p = &raw const s.unaligned; // not allowed with coercion
§4. Get it from C.
#[allow(unused_extern_crates)]
extern crate libc;
unsafe {
let my_num: *mut i32 = libc::malloc(size_of::<i32>()) as *mut i32;
if my_num.is_null() {
panic!("failed to allocate memory");
}
libc::free(my_num as *mut core::ffi::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 raw pointers in Rust.
Implementations§
Source§impl<T: PointeeSized> *const T
impl<T: PointeeSized> *const T
1.0.0 (const: 1.84.0) · Sourcepub const fn is_null(self) -> bool
pub const fn is_null(self) -> bool
Returns true
if the pointer is null.
Note that unsized types have many possible null pointers, as only the raw data pointer is considered, not their length, vtable, etc. Therefore, two pointers that are null may still not compare equal to each other.
§Panics during const evaluation
If this method is used during const evaluation, and self
is a pointer
that is offset beyond the bounds of the memory it initially pointed to,
then there might not be enough information to determine whether the
pointer is null. This is because the absolute address in memory is not
known at compile time. If the nullness of the pointer cannot be
determined, this method will panic.
In-bounds pointers are never null, so the method will never panic for such pointers.
§Examples
1.38.0 (const: 1.38.0) · Sourcepub const fn cast<U>(self) -> *const U
pub const fn cast<U>(self) -> *const U
Casts to a pointer of another type.
Sourcepub fn try_cast_aligned<U>(self) -> Option<*const U>
🔬This is a nightly-only experimental API. (pointer_try_cast_aligned
#141221)
pub fn try_cast_aligned<U>(self) -> Option<*const U>
pointer_try_cast_aligned
#141221)Try to cast to a pointer of another type by checking alignment.
If the pointer is properly aligned to the target type, it will be
cast to the target type. Otherwise, None
is returned.
§Examples
1.84.0 · Sourcepub fn addr(self) -> usize
pub fn addr(self) -> usize
Gets the “address” portion of the pointer.
This is similar to self as usize
, except that the provenance of
the pointer is discarded and not exposed. This means that
casting the returned address back to a pointer yields a pointer without
provenance, which is undefined behavior to dereference. To properly
restore the lost information and obtain a dereferenceable pointer, use
[with_addr
][pointer::with_addr] or [map_addr
][pointer::map_addr].
If using those APIs is not possible because there is no way to preserve a pointer with the
required provenance, then Strict Provenance might not be for you. Use pointer-integer casts
or [expose_provenance
][pointer::expose_provenance] and [with_exposed_provenance
][with_exposed_provenance]
instead. However, note that this makes your code less portable and less amenable to tools
that check for compliance with the Rust memory model.
On most platforms this will produce a value with the same bytes as the original pointer, because all the bytes are dedicated to describing the address. Platforms which need to store additional information in the pointer may perform a change of representation to produce a value containing only the address portion of the pointer. What that means is up to the platform to define.
This is a Strict Provenance API.
Sourcepub const fn guaranteed_eq(self, other: *const T) -> Option<bool>where
T: Sized,
🔬This is a nightly-only experimental API. (const_raw_ptr_comparison
#53020)
pub const fn guaranteed_eq(self, other: *const T) -> Option<bool>where
T: Sized,
const_raw_ptr_comparison
#53020)Returns whether two pointers are guaranteed to be equal.
At runtime this function behaves like Some(self == other)
.
However, in some contexts (e.g., compile-time evaluation),
it is not always possible to determine equality of two pointers, so this function may
spuriously return None
for pointers that later actually turn out to have its equality known.
But when it returns Some
, the pointers’ equality is guaranteed to be known.
The return value may change from Some
to None
and vice versa depending on the compiler
version and unsafe code must not
rely on the result of this function for soundness. It is suggested to only use this function
for performance optimizations where spurious None
return values by this function do not
affect the outcome, but just the performance.
The consequences of using this method to make runtime and compile-time code behave
differently have not been explored. This method should not be used to introduce such
differences, and it should also not be stabilized before we have a better understanding
of this issue.
Sourcepub fn is_aligned_to(self, align: usize) -> bool
🔬This is a nightly-only experimental API. (pointer_is_aligned_to
#96284)
pub fn is_aligned_to(self, align: usize) -> bool
pointer_is_aligned_to
#96284)Returns whether the pointer is aligned to align
.
For non-Sized
pointees this operation considers only the data pointer,
ignoring the metadata.
§Panics
The function panics if align
is not a power-of-two (this includes 0).
§Examples
#![feature(pointer_is_aligned_to)]
// On some platforms, the alignment of i32 is less than 4.
#[repr(align(4))]
struct AlignedI32(i32);
let data = AlignedI32(42);
let ptr = &data as *const AlignedI32;
assert!(ptr.is_aligned_to(1));
assert!(ptr.is_aligned_to(2));
assert!(ptr.is_aligned_to(4));
assert!(ptr.wrapping_byte_add(2).is_aligned_to(2));
assert!(!ptr.wrapping_byte_add(2).is_aligned_to(4));
assert_ne!(ptr.is_aligned_to(8), ptr.wrapping_add(1).is_aligned_to(8));
Source§impl<T: PointeeSized> *mut T
impl<T: PointeeSized> *mut T
Trait Implementations§
1.0.0 · Source§impl<T: PointeeSized> Clone for *const T
impl<T: PointeeSized> Clone for *const T
1.0.0 · Source§impl<T: PointeeSized> Clone for *mut T
impl<T: PointeeSized> Clone for *mut T
1.0.0 · Source§impl<T: PointeeSized> PartialEq for *const T
Pointer equality is by address, as produced by the <*const T>::addr
method.
impl<T: PointeeSized> PartialEq for *const T
Pointer equality is by address, as produced by the <*const T>::addr
method.
impl<'a, T: PointeeSized + Unsize<U>, U: PointeeSized> CoerceUnsized<*const U> for &'a T
impl<'a, T: PointeeSized + Unsize<U>, U: PointeeSized> CoerceUnsized<*const U> for &'a mut T
impl<T: PointeeSized + Unsize<U>, U: PointeeSized> CoerceUnsized<*const U> for *const T
impl<T: PointeeSized + Unsize<U>, U: PointeeSized> CoerceUnsized<*const U> for *mut T
impl<'a, T: PointeeSized + Unsize<U>, U: PointeeSized> CoerceUnsized<*mut U> for &'a mut T
impl<T: PointeeSized + Unsize<U>, U: PointeeSized> CoerceUnsized<*mut U> for *mut T
impl<T: ?Sized> Copy for *const T
impl<T: ?Sized> Copy for *mut T
impl<T: PointeeSized + Unsize<U>, U: PointeeSized> DispatchFromDyn<*const U> for *const T
impl<T: PointeeSized + Unsize<U>, U: PointeeSized> DispatchFromDyn<*mut U> for *mut T
impl<T: PointeeSized> Eq for *const T
Pointer equality is an equivalence relation.