新的IntPtr.Add方法 - 我错过了int的观点吗?

时间:2010-11-24 13:55:33

标签: c# .net .net-4.0 intptr pointer-arithmetic

从FW 4.0开始,IntPtr structure具有Add方法:

public static IntPtr Add(
    IntPtr pointer,
    int offset
)

哪个好,因为它应该解决我们所拥有的IntPtr数学问题(12,可能更多)。

但为什么offset int? 一定不是IntPtr吗?我可以很容易地想象将64位指针偏移超出int范围的值。


例如,考虑Marshal.OffsetOf

public static IntPtr OffsetOf(
    Type t,
    string fieldName
)

它返回IntPtr作为结构成员的偏移量。这很有道理!并且您无法使用新的Add方法轻松使用此偏移量。您必须将其转换为Int64,然后在循环中多次调用Add

此外,它似乎扼杀了IntPtr.Size与正确编写的应用程序无关的想法。您必须将偏移量转换为特定类型,例如Int64,此时您必须开始管理大小差异。并显示出现128位IntPtr时会发生什么。


我的问题是,为什么? 我的结论是正确的,还是我忽略了这一点?

2 个答案:

答案 0 :(得分:5)

它对应于x64架构中的限制。相对寻址仅限于带符号的32位偏移值。 Matt Pietrek在this article中提到了这一点(附近“幸运的是,答案是否定的”)。此限制还解释了为什么.NET对象在64位模式下仍限制为2GB。同样,在本机x64 C / C ++代码中,内存分配也受到限制。这不是不可能的,位移可以存储在64位寄存器中,只是这会使数组索引 lot 更加昂贵。

Marshal.OffsetOf()的神秘返回类型可能是一个角落案例。应用[StructLayout]和[MarshalAs]大于2GB后,托管结构可能会导致非托管版本。

是的,这不会很好地映射到未来的128位架构。但是当没有人知道它的外观时,准备今天的软件是非常困难的。也许古老的谚语很合适,对于任何人来说,16太字节应该足够了。还有很多的空间可以超越它,2 ^ 64相当大。当前的64位处理器仅实现2 ^ 48。在机器可以移动之前,需要解决一些严重的非平凡问题。

答案 1 :(得分:1)

如果您只定义:

public static IntPtr Add(IntPtr pointer, IntPtr offset)

然后,向64位指针添加32位偏移量的可读性较差,恕我直言。

再次,如果你定义

public static IntPtr Add(IntPtr pointer, long offset)

然后,向32位指针添加64位偏移量也很糟糕。

顺便说一下, Substract 会返回一个IntPtr,所以无论如何IntPtr逻辑都没有被破坏。