Hello,
How can one do pointer artihmetic in nim? I had to cheat with a fake uint8 type to make it work:
type
UDP_packet = tuple
port_src: uint16
port_dst: uint16
length: uint16
chksum: uint16
data:char #cheat here but works perfectly
var my_str = "hi, it is me"
copyMem(addr t.data, addr mystr[0], mystr.len)
but I would have preferred something like
copyMem(addr t + sizeof(UDP_packet), addr mystr[0], mystr.len)
Thankspointer arithmetic is possible in Nim, but you should reeaaaally use them only for FFI and not in your daily.
Since int has the size of a pointer in Nim, you can do this:
copyMem(cast[ptr UDP_packet](cast[int](addr t)+sizeof(UDP_packet)),addr my_str[0], my_str.len)
Though you really shouldn't do this, unless there's no way around it.
You might be interested in UncheckedArray s, since they can often replace pointer arithmetic with something far safer(but still not safe).
You can refer to 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]
Alternatively I've also resorted to emitting C:
func `+`*(p: ptr, offset: int): type(p) {.inline.}=
## Pointer increment
{.emit: "`result` = `p` + `offset`;".}
I strongly suggest not to define += though. Normally it should be defined with the following signature:
func `+`*(p: var ptr, offset: int) {.inline.}=
## Pointer increment
{.emit: "`p` += `offset`;".}
But in Nim a var is passed by hidden pointer and you will increment this hidden pointer instead of the actual pointer, so you need to dereference it in the code.
func `+`*(p: var ptr, offset: int) {.inline.}=
## Pointer increment
{.emit: "*`p` += `offset`;".}
But as @doofenstein said, ptr UncheckedArray[T] covers a lot of need by giving you array indexing on arbitrary ranges.
Thanks You,
Both of you are right. I will use my strategy right now because the struct is easy but I will definitely use uncheckedarrays should the context be more complex. Flat memory layout is easy enough.
Sorry, but the rest is.. not elegant->ugly.
Thank you both!!
Thank you so much,
Nim is a wonderful language. Wow. Creating tools with it is so simple!
I find the power of C without the ugliness.
Its purpose is to facilitate manual memory management, and there are plenty of proc to manage them in the stdlib.
You can also create a ptr pointing to a variable with the addr operator.