Pointers
All objects are passed by value and as such copied. That means once you pass a value somewhere, it exists as a separate entity from the original.
use std::*;
fn increment(v: u32) {
v += 1;
c_api::printf("incremented: %d", v);
}
fn main() {
let value = 4;
increment(value);
c_api::printf("not incremented: %d", value);
}
Increment gets a copy of value
and as such the original is not incremented.
This can however be done by explicitly taking a reference:
use std::*;
fn increment(v: &i32) { // v points to value
*v += 1; // increment the value pointed to by v
c_api::printf("incremented: %d\n", *v); // read the value pointed to by v
}
fn main() {
let value = 4;
let points_to_value = &value; // point to value
increment(points_to_value);
c_api::printf("now also incremented: %d\n", value);
}
Here we take a reference of value
by using the &
prefix operator.
To access the inner value inside the pointer, we need to dereference it using the *
prefix operator.
Note: The cannonical name of a reference
&T
isptr<T>
. The compiler will give you a hint so that you may replace it with&T
. To see this in the online editor, enable thecompiler output
checkbox. To disable those warnigns entirely, set he--no-lint
flag. If you specifically want to use the canonical name, use the fully qualified path:::core::types::ptr<T>
to disable warnings.
A pointer is only valid as long as the original object is valid:
use std::*;
fn create_pointer() -> &i32 {
let value = 4;
let p = &value; // create pointer to value
p // value still exists...
} // value gets removed at end of function, p is now invalid!
fn main() {
// p is invalid here since value was already removed
let p = create_pointer();
}
p
may now have any and all states, or may even crash the program when used.
Even if the original object is still around but was moved, p
is still invalid, since in both cases the pointed-to value is no longer where p
points to.
Unlike c, pointers of literals are supported:
use std::*;
fn increment(v: &i32) { // v points to value
*v += 1; // increment the value pointed to by v
c_api::printf("incremented: %d\n", *v); // read the value pointed to by v
}
fn main() {
increment(&1);
}
This is equivalent to the following c code:
#include <stdio.h>
void increment(int* v) { // v points to value
*v += 1; // increment the value pointed to by v
printf("incremented: %d\n", *v); // read the value pointed to by v
}
int main() {
int _temp = 1;
increment(&_temp);
}
The pointer is only valid for the duration of the function call:
use std::*;
fn identity<T>(x: T) -> T {
// x is still valid here
x // passthrough
}
fn main() {
let now_invalid_ptr = identity(&1);
}