I was just going to add an example for pointer arithmetic, see
http://ssalewski.de/nimprogramming.html#_pointer_arithmetic
The line
var h = cast[int](p); h += sizeof(a[0]); p = cast[ptr int](h)
in the example code
proc main =
var
a: array[8, int] = [0, 1, 2, 3, 4, 5, 6, 7]
sum = 0
var p: ptr int = addr(a[0])
for i in a.low .. a.high:
echo p[]
sum += p[]
echo cast[int](p)
var h = cast[int](p); h += sizeof(a[0]); p = cast[ptr int](h)
#cast[var int](p) += sizeof(a[0])
echo sum
echo typeof(sizeof(a[0]))
main()
is clumsy. From my memory casting to var was working some years ago, so I also tried a construct like
cast[var int](p) += sizeof(a[0])
but that seems not to work with
Nim Compiler Version 1.3.5 [Linux: amd64]
Compiled at 2020-09-05
Can we improve that example?
use uint instead of int
That is an interesting point.
ptr UncheckedArray[T]
Yes I know UncheckedArray, I am not sure if it is already mentioned in the book, but I will explain that of course.
But we have to give some examples for pointer arithmetic, people coming from C ask for it from time to time.
You cannot cast to a var type (you might be able to on devel with views, but that's besides the point). I believe what people do in general is:
var s = @[1, 2, 3, 4, 5]
var p = addr s[0]
echo p[] # 1
cast[ptr int](addr p)[] += sizeof(int)
echo p[] # 2
I found again where I used cast[var successfully:
https://forum.nim-lang.org/t/6412#39551
p3(castvar int)
There is ByteAddress which should be used for this purpose.
recently i used this:
template `[]`(mem: pointer, pos: uint): char =
cast[ptr char](cast[ByteAddress](mem) + pos.ByteAddress)[]
You cannot cast to a var type
Maybe than it should not compile, but it does.
I just remembered that someone made a package for pointer arithmetic, but maybe I am wrong. Will search tomorrow.
cast[var int](p) += sizeof(a[0])
compiles on 1.0.8,1.2.6 and devel which, i had no idea, and does turn a ptr int into a var int, so you're adding to the referred value.
and yes, UncheckedArray[T] is the way to assign to an array, but it doesn't make such a great example because it just hides all the math.
what about offsets in structs?
type
Big{.packed.} = object
i: int64
j: int32
k: int8
l: string
var b = Big(i: 3, j: 5, k: 7, l: "nine")
let p = b.addr
echo b
cast[var int64](cast[ByteAddress](p) +% offsetOf(Big, i)) += 3
cast[var int32](cast[ByteAddress](p) +% offsetOf(Big, j)) += 4
cast[var int8]( cast[ByteAddress](p) +% offsetOf(Big, k)) += 5
cast[var string](cast[ByteAddress](p) +% offsetOf(Big, l)) &= "r"
echo b
outputs:
(i: 3, j: 5, k: 7, l: "nine")
(i: 6, j: 9, k: 12, l: "niner")
still a terrible example, i don't know why you'd do that but hey, you can.
Interesting.
var s = @[1, 2, 3, 4, 5]
var p = addr s[0]
echo p[] # 1
echo type(p)
echo type((addr p)[])
echo type(cast[ptr int](addr p)[])
cast[var int](addr p) += sizeof(s[0])
echo p[]
cast[ptr int](addr p)[] += sizeof(s[0])
echo p[]
1
ptr int
ptr int
int
2
3
So
cast[ptr int](q)[]
is the same as
cast[var int](q)
That's a revelation to me.Sad that he left Nim.
What happened?
Oddly, I cannot search for his posts here, as if the search engine ignores his name. I used to read every post he made.