Pointers, References, and Raw Pointers
C uses T * everywhere. It can mean many different things:
void print_config(const struct Config *cfg);
void reset_config(struct Config *cfg);
int parse_packet(const uint8_t *data, size_t len, struct Packet *out);
void driver_write(void *addr, uint32_t value);
These all look like pointers, but the meanings differ:
- read-only access to an object
- mutation of a caller-provided object
- pointer plus length for a buffer
- output parameter
- nullable pointer
- hardware address or FFI-provided address
Rust does not put all of these into one pointer concept. Start with this table:
const T * -> &T / Option<&T>
T * -> &mut T / Option<&mut T>
const T * + len -> &[T]
T * + capacity -> &mut [T]
out parameter -> return value / &mut T / &mut [T]
void * -> generic, trait, raw pointer, or FFI context
real address / FFI ptr -> *const T / *mut T
The first layer is the split itself: ordinary library APIs should prefer references and slices, while raw pointers should stay close to FFI, hardware addresses, and low-level wrappers.
Read More