The following program generates the errors:
t.nim(15, 17) template/generic instantiation from here
t.nim(5, 28) Error: expression has no address
Why does the expression buffer[0] have no address?
import endians
import strutils
proc parse[T](buffer: openArray[uint8]): T =
let pointer = addr(buffer[0])
when sizeof(T) == 2:
littleEndian16(addr(result), pointer)
elif sizeof(T) == 4:
littleEndian32(addr(result), pointer)
else:
result = (T)42
var buffer = [0x01'u8, 0x23, 0x45, 0x67]
echo toHex(parse[uint16](buffer))
echo toHex(parse[uint32](buffer))
Is the rule that variables defined with var have addresses and defined with let do not?
It seems like defining the proc without the var is the right thing to do since the procedure is not modifying the array or sequence passed in.
It would be convenient to be able to pass let variables to the procedure too:
let buffer = [0x01'u8, 0x23, 0x45, 0x67]
Do I need to rewrite the endian procedures so they don't require addresses to be able to get what I want? Can someone explain the issues to me?
The argument when not stated, is using let , in other word it's like put the variable in stack, that's why it has no address. To bypass that, you must pass the var to the argument so it's using the same memory place in heap.
import endians
import strutils
proc parse[T](buffer: var openArray[uint8]): T =
let pointer = addr(buffer[0])
when sizeof(T) == 2:
littleEndian16(addr(result), pointer)
elif sizeof(T) == 4:
littleEndian32(addr(result), pointer)
else:
result = (T)42
var buffer = [0x01'u8, 0x23, 0x45, 0x67]
echo toHex(parse[uint16](buffer))
echo toHex(parse[uint32](buffer))
A non-var argument has "no address" so that nothing inside the proc can "take the pointer and run" with an immutable parameter.
If you need to, you can explicitly use unsafeAddr which means "i know what I'm doing and I won't let the parameter escape".
Or if you want to mutate it, use a var param.