As implies, a pointer to memory.

MSP + PSP

Main stack pointer and processes stack pointers respectively. The MSP is essentially exclusively used in Interrupt Service Routines. The PSP holds the address of the currently running thread since each thread has its own stack. The PSP is never used in interrupts.

Void Pointer

We might need a pointer but might now know or care at compile-time what type that pointer is. You cannot dereference these.

Function Pointer

You use a pointer to the function and a pointer to its arguments. You can kind of use these like callbacks?

Pointers Diagram

Volatile

Volatile doesn’t store values in cache (skips this optimization) so that when something external to the processor changes a value, a volatile variable knows the value is changed.
When a variable can be changed externally, use volatile.

GoLang

Pointer syntax has the same semantic meaning as normal

    • → Pointer
  • & → Address Where we can perform dereferencing techniques as well.

The thing that trips me up is…

Pointer Casting Example. Avoiding Mutexes

Related concepts: Synchronization

In this example: *j = MetadataJSON(*metadata), we copy everything from metadata and assign the copy to j. Here, if metadata has a hidden synchronization mechanism because j contains protobuf messages, it also copies that mechanism…

Here:

  • *metadata dereferences pointer the copies entire struct (including mutex)
  • MetadataJSON(...) converts the copied struct
  • *j = ... assigns the converted copy

This is bad because now we have two copies of the same sync mechanism…

  • This can result in data races

The solution:

  • *j = *(*MetadataJSON)(metadata)

Here:

  • (*GymMetadataJSON)(metadata) casts pointer type (no copying)
  • *(...) dereferences the casted pointer
  • *j = ... assigns the value

We don’t copy anything here, but rather just cast at the pointer level and assign to j which doesn’t copy over the mutex.