Hey there, authore of Arraymancer here.
Accessing elements using ptr arithmetic:
* Usually you when you need pointer arithmetics you actually need pointer
indexing similar to:
let rawBuffer = [0, 1, 2, 3, 4, 5]
# use unsafeAddr if let variable
# or addr if var variable
# (Security so you don't escape with a pointer to an immutable variable
# by mistake, say when refactoring)
let a = cast[ptr UncheckedArray[int]](rawBuffer[0].unsafeAddr)
echo a[0]
echo a[4]
Run
i.e. ptr UncheckedArray gives you array semantics on pointers.
* For pointer arithmetics, if you really needs them, you can follow this post
for a safe well defined scope in which pointer arithmetics is allowed:
[https://forum.nim-lang.org/t/1188#7366](https://forum.nim-lang.org/t/1188#7366)
template ptrMath*(body: untyped) =
template `+`*[T](p: ptr T, off: int): ptr T =
cast[ptr type(p[])](cast[ByteAddress](p) +% off * sizeof(p[]))
template `+=`*[T](p: ptr T, off: int) =
p = p + off
template `-`*[T](p: ptr T, off: int): ptr T =
cast[ptr type(p[])](cast[ByteAddress](p) -% off * sizeof(p[]))
template `-=`*[T](p: ptr T, off: int) =
p = p - off
template `[]`*[T](p: ptr T, off: int): T =
(p + off)[]
template `[]=`*[T](p: ptr T, off: int, val: T) =
(p + off)[] = val
body
when isMainModule:
ptrMath:
var a: array[0..3, int]
for i in a.low..a.high:
a[i] += i
var p = addr(a[0])
p += 1
p[0] -= 2
echo p[0], " ", p[1]
Run
* Alternatively, for lower overhead this is [what I use in
Laser](https://github.com/numforge/laser/blob/27e4a77c7808ac5b5dcee08ddf3baa320aed47c8/laser/primitives/matrix_multiplication/gemm_utils.nim#L16-L18),
the future very low-level machine and deep learning backend of Arraymancer:
# Warning for pointer arithmetics be careful of not passing a `var ptr`
# to a function as `var` are passed by hidden pointers in Nim and the
wrong
# pointer will be modified. Templates are fine.
func `+`*(p: ptr, offset: int): type(p) {.inline.}=
## Pointer increment
{.emit: "`result` = `p` + `offset`;".}
Run
`+=` should be defined in terms of `+` because `var` are passed by hidden
pointers and the wrong pointer will be updated if you use "emit".