The new IntPtr.Add method - am I missing the point of the int?

狂风中的少年 提交于 2019-12-10 23:43:28

问题


Starting from FW 4.0, the IntPtr structure has the Add method:

public static IntPtr Add(
    IntPtr pointer,
    int offset
)

Which is great, as it's supposed to address all those questions on IntPtr math we have had (1, 2, probably more).

But why is the offset int?
Must it not be IntPtr? I can easily imagine offsetting a 64-bit pointer by a value which is beyond the int range.


For instance, consider Marshal.OffsetOf:

public static IntPtr OffsetOf(
    Type t,
    string fieldName
)

It returns an IntPtr as the offset to the structure member. Which makes perfect sense! And you cannot easily use this offset with the new Add method. You'd have to cast it to Int64, then call Add several times in a loop.

Also, it seems to kill the very idea of the IntPtr.Size being irrelevant to a properly written application. You will have to cast the offset to a particular type, such as Int64, at which point you must start managing the size difference. And image what will happen when 128-bit IntPtr appears.


My question here is, why?
Am I correct in my conclusions, or am I missing the point?


回答1:


It corresponds to a restriction in the x64 architecture. Relative addressing is limited to a signed 32-bit offset value. Matt Pietrek mentions this in this article (near "Luckily, the answer is no"). This restriction also explains why .NET objects are still limited to 2GB in 64-bit mode. Similarly, in native x64 C/C++ code memory allocations are limited as well. It is not that it is impossible, the displacement could be stored in a 64-bit register, it is just that this would make array indexing a lot more expensive.

The mysterious return type of Marshal.OffsetOf() is probably a corner-case. A managed struct could result in an unmanaged version after applying [StructLayout] and [MarshalAs] that's larger than 2GB.

Yes, this wouldn't map well to some future 128-bit architecture. But it is extraordinarily difficult to prep today's software for an arch when nobody knows what it will look like. Perhaps the old adage fits, 16 Terabytes ought to be enough for anybody. And there's lots of room left to grow beyond that, 2^64 is rather a large number. Current 64-bit processors only implement 2^48. Some seriously non-trivial problems need to be solved before machines can move that close.




回答2:


If you define only:

public static IntPtr Add(IntPtr pointer, IntPtr offset)

then, adding a 32 bits offset to a 64 bits pointer is less readable, IMHO.

Again, if you define

public static IntPtr Add(IntPtr pointer, long offset)

then, adding a 64 bits offset to a 32 bits pointer is also bad.

By the way, Substract returns an IntPtr, so the IntPtr logic is not broken in anyway.



来源:https://stackoverflow.com/questions/4267531/the-new-intptr-add-method-am-i-missing-the-point-of-the-int

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!