Pointers in Nim

import std/strformat

# We'll show how pointers work in contrast to values with
# 2 procedures: `zeroval` and `zeroptr`. `zeroval` has an
# `int` parameter, so arguments will be passed to it by
# value. `zeroval` will get a copy of `ival` distinct
# from the one in the calling procedure.
proc zeroval(ival: int) =
  var ival = ival  # Create a mutable copy
  ival = 0

# `zeroptr` in contrast has a `ptr int` parameter, meaning
# that it takes an `int` pointer. The `iptr[]` syntax in the
# procedure body then dereferences the pointer.
# Assigning a value to a dereferenced pointer changes the
# value at the referenced address.
proc zeroptr(iptr: ptr int) =
  iptr[] = 0

proc main() =
  var i = 1
  echo fmt"initial: {i}"

  zeroval(i)
  echo fmt"zeroval: {i}"

  # The `addr` function gives the memory address of `i`,
  # i.e. a pointer to `i`.
  zeroptr(addr i)
  echo fmt"zeroptr: {i}"

  # Pointers can be printed too.
  echo fmt"pointer: {cast[int](addr i)}"

main()

Nim supports pointers, allowing you to pass references to values and records within your program.

In this example, we demonstrate how pointers work in contrast to values using two procedures: zeroval and zeroptr.

The zeroval procedure takes an int parameter, so arguments are passed to it by value. This means zeroval receives a copy of the value, distinct from the one in the calling procedure.

The zeroptr procedure, on the other hand, takes a ptr int parameter, which is a pointer to an int. Inside the procedure, we use the iptr[] syntax to dereference the pointer and access or modify the value it points to.

In the main procedure, we create a variable i and demonstrate the difference between passing by value and passing by reference:

  1. We pass i to zeroval, which doesn’t change the original i.
  2. We pass addr i (the address of i) to zeroptr, which does change the original i because it has a reference to the memory address of that variable.

Finally, we print the pointer itself, which is the memory address of i. In Nim, we need to cast the pointer to an integer to print its raw value.

To run this program, save it as pointers.nim and use the Nim compiler:

$ nim c -r pointers.nim
initial: 1
zeroval: 1
zeroptr: 0
pointer: 140732920764540

Note that zeroval doesn’t change the i in main, but zeroptr does because it has a reference to the memory address for that variable.