Новый метод IntPtr.Add - я упустил смысл int?

Начиная с FW 4.0, IntPtr структура имеет структуру 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.


Мой вопрос в том, почему?
Прав ли я в своих выводах или упускаю суть?


person GSerg    schedule 24.11.2010    source источник


Ответы (2)


Это соответствует ограничению в архитектуре x64. Относительная адресация ограничена 32-битным значением смещения со знаком. Мэтт Питрек упоминает об этом в этой статье (рядом с надписью "К счастью, ответ нет»). Это ограничение также объясняет, почему объекты .NET по-прежнему ограничены 2 ГБ в 64-разрядном режиме. Точно так же в собственном коде x64 C/C++ выделение памяти также ограничено. Дело не в том, что это невозможно, смещение можно хранить в 64-битном регистре, просто это сделало бы индексацию массива намного дороже.

Таинственный возвращаемый тип Marshal.OffsetOf(), вероятно, является крайним случаем. Управляемая структура может привести к созданию неуправляемой версии после применения [StructLayout] и [MarshalAs], размер которой превышает 2 ГБ.

Да, это не будет хорошо соответствовать будущей 128-битной архитектуре. Но чрезвычайно сложно подготовить сегодняшнее программное обеспечение к архитектуре, когда никто не знает, как оно будет выглядеть. Возможно, подходит старая поговорка: 16 терабайт должно быть достаточно для всех. Кроме того, осталось много места для роста, 2^64 — довольно большое число. Текущие 64-битные процессоры реализуют только 2^48. Прежде чем машины смогут подойти так близко, необходимо решить некоторые серьезные нетривиальные проблемы.

person Hans Passant    schedule 24.11.2010

Если вы определяете только:

public static IntPtr Add(IntPtr pointer, IntPtr offset)

тогда добавление 32-битного смещения к 64-битному указателю менее читабельно, ИМХО.

Опять же, если вы определяете

public static IntPtr Add(IntPtr pointer, long offset)

тогда добавление 64-битного смещения к 32-битному указателю также плохо.

Кстати, Subtract возвращает IntPtr, так что логика IntPtr в любом случае не нарушена.

person Simon Mourier    schedule 24.11.2010