Raw Pointers

2 Posts

Pointers, References, and Raw Pointers

6 minute

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

unsafe: Keep C Risks at the Boundary

4 minute

C developers may first read unsafe as “the place where Rust lets me write C.”

That is too broad.

unsafe does not disable all Rust checks, and it does not turn a block back into C. It permits a small set of operations the compiler cannot prove safe, such as dereferencing raw pointers, calling FFI functions, and accessing mutable global state.

The key question is not whether unsafe can be written. It is how small the unsafe boundary can be.

Read More