IntPtr дополнение - PullRequest
       41

IntPtr дополнение

1 голос
/ 10 ноября 2009

Итак, из того, что я могу сказать, каждый управляемый пример добавления IntPtr, который я нашел, это НЕПРАВИЛЬНО .

Например: http://www.atalasoft.com/cs/blogs/stevehawley/archive/2006/10/16/10987.aspx

Я думал, что если IntPtr имеет значение (или близко) к int32.MaxValue в 32-разрядной системе, и вы добавляете смещение, которое переполняет int32, то это не является действительным адресом памяти (как это было бы верно в uint32, и будет представлен отрицательным числом в IntPtr)?!

Я считаю, что код должен выглядеть примерно так:

public static IntPtr Offset(IntPtr src, int offset)
{
    switch (IntPtr.Size) {
    case 4:
        return new IntPtr((int)((uint)src + offset));
    case 8:
        return new IntPtr((long)((ulong)src + offset));
    default:
        throw new NotSupportedException("Not supported");
    }
}

Я сумасшедший?

Есть ли у кого-нибудь проверенный пример добавления IntPtr?

Ответы [ 3 ]

1 голос
/ 10 ноября 2009

Я думаю, дело в том, что если вы переполните int, вы все равно получите соответствующее значение. Попробуйте это:

//-2147483645
Console.WriteLine( int.MaxValue + 4 );

//2147483651
Console.WriteLine( (uint)(int.MaxValue + 4) );

Учитывая, что int.MaxValue равно 2147483647, приведение переполненного отрицательного числа к uint действительно дает правильное значение.

1 голос
/ 22 апреля 2010

.NET 4.0 добавляет новый статический метод IntPtr.Add (указатель IntPtr, смещение int).

В более ранних версиях .NET альтернативным способом преобразования в целое число является использование «небезопасного» блока кода и приведение IntPtr к (байту *). Выполните добавление и верните результат обратно в IntPtr. Компилятор заботится о деталях ширины указателя. : -)

Пример:

  new IntPtr((byte *)pipe.Root + EventNameOffset)

или

  (IntPtr)((byte *)pipe.Root + EventNameOffset)
0 голосов
/ 10 ноября 2009

Перед добавлением IntPtr приводится к uint, затем применяется смещение. Это будет работать правильно, но результатом будет long.

Насколько я знаю, добавление ulong и int невозможно, поэтому 64-битная часть указателя неверна. На самом деле это даже не компилируется. Я не могу придумать элегантного решения, но просто использование long, вероятно, будет безопасным. Это половина загрузки памяти *, которую вы могли бы использовать *, 8 экзабайт :) Тем не менее, теоретически сопоставление адресов памяти может быть проблемой.

*: хорошо, если текущая реализация .NET Framework не помешает вам сделать это long до этого, конечно:)

...