什么是Addr#类型,我该如何使用它?

时间:2015-09-11 18:20:05

标签: haskell primitive-types

当我发现Addr#类型时,我最近一直在环顾各种Haskell怪癖,比如未装箱的类型等等。

GHC.Prim包描述如下:

  

假定任意机器地址指向垃圾收集堆之外。

这对我来说意义不大。

此外,我一直在寻找使用类型的函数:

readIntOffAddr# :: Addr# -> Int# -> State# s -> (#State# s, Int##)

这是什么类型的?我该怎么办?为什么有必要?

2 个答案:

答案 0 :(得分:8)

作为迈克尔回答的补充:

Addr#Ptr a下的未装箱类型,与Int#Int下的未装箱类型的方式相同。其内容可能被解释为机器地址,但就编译器和GC而言,它只是另一种整数类型(无论系统中的大小指针是什么)。因为它是一个任意的机器地址而不是GC管理的指针,所以它应该不会指向Haskell堆,因为Haskell堆对象的地址从Haskell级别看是不稳定的(GC可能在任何一点发生)你的程序,然后你Addr#所指向的任何对象都存在于其他地方,或者根本没有任何对象。

通常Ptr a / Addr#将包含从malloc / mmap /等返回的指针,或指向C全局变量的指针,或者通常任何指针指针可能在C程序中明显指向的东西。通常在与C函数接口时使用readIntOffAddr#,该函数返回或修改传递的HsInt *的内容。 (好吧,你不会直接使用它,你会使用Int的{​​{1}} peekElemOff方法,我认为这是按照Storable实现的,或者你会使用更高级别的函数,如readIntOffAddr#)。

答案 1 :(得分:7)

等效的* C代码为:

long readIntOffAddr(long *ptr, long offset) {
    return ptr[offset];
}

Addr#就像void *一样。该函数具有IO - 类似签名,因为它不是纯粹的#34;。多次调用函数可能会返回不同的值(显然)。

* 更新(2018年):我刚刚了解到将C&#39 {1}}类型与Haskell int类型等同是错误的。因此,我在上面的代码段中将Int#更改为int。这也(可能)不是100%正确,但至少对于我所见过的所有GHC实现都是如此。在GHC版本6-8(没有检查其他版本)中,long在32位平台上为32位宽,在64位平台上为64位宽。这与我所知道的32位和64位平台上所有C / C ++实现的Int#的GCC行为相匹配,所以我认为将longInt#等同起来是一个良好的第一近似。在过去3年中没有人注意到这种轻微的不准确性(或者足以编辑/评论),所以请不要为此向我投降。我怀疑是否有任何Haskell / Platform / C组合long!= HsInt其中Haskell实现具有long函数..请证明我错了。