【问题标题】:The new IntPtr.Add method - am I missing the point of the int?新的 IntPtr.Add 方法 - 我错过了 int 的要点吗?
【发布时间】:2010-11-24 13:55:32
【问题描述】:

从 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 出现时会发生什么。


我的问题是,为什么?
我的结论是正确的,还是我没有抓住重点?

【问题讨论】:

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


    【解决方案1】:

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

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

    是的,这不能很好地映射到某些未来的 128 位架构。但是,当没有人知道它会是什么样子时,要为今天的软件准备拱门是非常困难的。也许这句老话适合,16 TB 对任何人来说都应该足够了。并且还有 很多 的空间可以增长,2^64 是一个相当大的数字。当前的 64 位处理器仅实现 2^48。在机器离得那么近之前,需要解决一些非常重要的问题。

    【讨论】:

      【解决方案2】:

      如果你只定义:

      public static IntPtr Add(IntPtr pointer, IntPtr offset)
      

      那么,将 32 位偏移量添加到 64 位指针的可读性较差,恕我直言。

      再次,如果你定义

      public static IntPtr Add(IntPtr pointer, long offset)
      

      那么,将 64 位偏移量添加到 32 位指针也是不好的。

      顺便说一句,Substract 返回一个 IntPtr,因此 IntPtr 逻辑无论如何都不会中断。

      【讨论】:

        猜你喜欢
        • 2022-07-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-08-29
        • 2017-10-19
        • 2012-02-11
        相关资源
        最近更新 更多