从FW 4.0开始,IntPtr
structure具有Add
方法:
public static IntPtr Add(
IntPtr pointer,
int offset
)
哪个好,因为它应该解决我们所拥有的IntPtr
数学问题(1,2,可能更多)。
但为什么offset
int
?
一定不是IntPtr
吗?我可以很容易地想象将64位指针偏移超出int
范围的值。
例如,考虑Marshal.OffsetOf
:
public static IntPtr OffsetOf(
Type t,
string fieldName
)
它返回IntPtr
作为结构成员的偏移量。这很有道理!并且您无法使用新的Add
方法轻松使用此偏移量。您必须将其转换为Int64
,然后在循环中多次调用Add
。
此外,它似乎扼杀了IntPtr.Size
与正确编写的应用程序无关的想法。您必须将偏移量转换为特定类型,例如Int64
,此时您必须开始管理大小差异。并显示出现128位IntPtr
时会发生什么。
我的问题是,为什么? 我的结论是正确的,还是我忽略了这一点?
答案 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逻辑都没有被破坏。