从固件 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
出现时会发生什么。
我的问题是,为什么?
我的结论是正确的,还是我没有捕获重点?
最佳答案
它对应于 x64 架构中的限制。相对寻址仅限于带符号的 32 位偏移值。 Matt Pietrek 在 this article 中提到了这一点(靠近“幸运的是,答案是否定的”)。此限制也解释了为什么 .NET 对象在 64 位模式下仍限制为 2GB。同样,在 native x64 C/C++ 代码中,内存分配也受到限制。并不是说不可能,位移可以存储在 64 位寄存器中,只是这会使数组索引变得很多更加昂贵。
Marshal.OffsetOf() 神秘的返回类型可能是一个极端情况。应用大于 2GB 的 [StructLayout] 和 [MarshalAs] 后,托管结构可能会产生非托管版本。
是的,这不能很好地映射到 future 的某些 128 位架构。但是,当没有人知道它会是什么样子时,为当今的拱门准备软件是非常困难的。也许古老的格言很合适,16 TB 对任何人来说都应该足够了。除此之外,还有很多的增长空间,2^64 是一个相当大的数字。当前的 64 位处理器仅实现 2^48。在机器能够移动得那么近之前,需要解决一些严重的、不平凡的问题。
关于c# - 新的 IntPtr.Add 方法 - 我是否错过了 int 的要点?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4267531/