Pointers

A pointer is an integer value representing a memory address. You can take the address of a value using the address-of operator &. A pointer to some type T is represented as ^T. This can be nested as much as you want, so ^^^^^T is a perfectly valid type. If you want to get the value out of a pointer , use the dereference operator ^, placed after the expression. This follows Odin's general rule of modifiers on the left and "undoing" those modifiers on the right.

Example:

my_number: int = 123
my_pointer: ^int = &my_number

assert(my_number == my_pointer^)

A dereference is a valid assignment target, which means you can use a pointer to pass around a value that can be modified, e.g.

double_int :: proc(x: ^int) {
    x^ = x * 2
}

x := 5
double_int(&x)
assert(x == 10)

Not every expression can have its address taken, here are a few common cases and their solutions:

Compound literals can be addressed, so &Foo{} is perfectly valid.

Multipointers

A multipointer is a pointer that can be indexed, with behavior like C. A multipointer type is written as [^]T. Multipointers are used most commonly when interfacing with C, but are sometimes found in other places. The most common way to get a multipointer is using the raw_data builtin procedure, but they can also be created directly with make.

Multipointers can be sliced, which will either give back another multipointer or a Slice, depending on whether or not you provide a length.

Example:

my_data: [^]int = make([^]int, 10)
// A slice, because it has a length
my_slice: []int = my_data[:10]
// A multipointer, because there's no length
my_data_again: [^]int = my_data[:]

Multipointers are the primary alternative to pointer arithmatic or pointer math in C. Here's an example of C code and equivalent Odin code:

const char *str = "Hello";

for (char *ptr = str; *ptr != 0; ptr++) {}
str: cstring = "Hello"
for ptr := transmute([^]u8)str; ptr[0] != 0; ptr = ptr[1:] {}

For more info about features used in this example, see Cstrings, transmute, Loops

Rawptr

Main article

rawptr is a pointer type representing a pointer to anything. It doesn't track what the type is that it's pointing to (for that, consider Any), so it's mainly used as a way to store unknown data. Most commonly it's used inside of callbacks from libraries, to allow you to pass as much arbitrary data into the callback as you want. It's equivalent to void * in C.

Uintptr

uintptr isn't necessarily a pointer type, but a pointer-sized integer type. While the difference is subtle, uintptr cannot be assigned nil, and supports integer operations such as + and -. It can, however, be cast to and from most pointer types, so it serves as the most fundamental form of pointer arithmatic in Odin.

Procedures

Procedure types are automatically pointers, so storing one in a variable creates a procedure pointer. They can be cast to rawptr and to other procedure types, but nothing else. You cannot dereference a procedure.