I've recently been looking around at various Haskell quirks, like unboxed types and whatnot, when I discovered the Addr#
type.
The GHC.Prim
package describes it as so:
An arbitrary machine address assumed to point outside the garbage-collected heap.
And that means not much to me.
Furthermore, I keep finding functions like this that use the type:
readIntOffAddr# :: Addr# -> Int# -> State# s -> (#State# s, Int##)
What is this type? What can I do with it? Why is it necessary?
As a complement to Michael's answer:
Addr#
is the unboxed type underlying a Ptr a
in the same way that Int#
is the unboxed type underlying an Int
. Its contents are presumably to be interpreted as a machine address, though as far as the compiler and GC are concerned it is just another integral type (of whatever size pointers are on the system in question). Since it is an arbitrary machine address and not a GC-managed pointer, it should presumably not point into the Haskell heap because the addresses of Haskell heap objects are not stable as viewed from the level of Haskell (a GC could occur at any point in your program, and then whatever object your Addr#
pointed at now lives elsewhere, or nowhere at all).
Normally a Ptr a
/Addr#
will contain a pointer returned from malloc
/mmap
/etc., or a pointer to a C global variable, or in general any sort of thing that a pointer might sensibly point to in a C program. You would normally use readIntOffAddr#
when interfacing with a C function that returns or modifies the contents of a passed HsInt *
. (Well, you wouldn't use it directly, you'd use Int
's peekElemOff
Storable
method which I presume is implemented in terms of readIntOffAddr#
, or you would use an even higher-level function like peekArray
).
The equivalent* C code would be:
long readIntOffAddr(long *ptr, long offset) {
return ptr[offset];
}
Addr#
is just like void *
. The function has an IO
-like signature because it is not "pure". Multiple calls to the function may return different values (obviously).
* Update (2018): I just learned that equating C's int
type with Haskells Int#
type is wrong. So I changed int
to long
in the above code snippet. This is also (maybe) not 100% correct, but at least it is true for all GHC implementations that I have seen. In GHC versions 6-8 (haven't checked others), Int#
is 32 bit wide on 32-bit platforms and 64 bit wide on 64-bit platforms. This matches the behaviour of GCC for long
for all C/C++ implementations on 32-bit and 64-bit platforms that I am aware of, so I think equating Int#
with long
is a good first approximation. No one noticed this minor inaccuracy in the last 3 years (or cared enough to edit/comment). I doubt that there is any Haskell/Platform/C combination where HsInt
!= long
where the Haskell implementation has a readIntOffAddr#
function.. please prove me wrong.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With