c # указатели против IntPtr - PullRequest
9 голосов
/ 01 декабря 2010

это вторая часть первого вопроса с использованием указателей c #

поэтому указатели в c # являются «небезопасными» и не управляются сборщиком мусора, в то время как IntPtr является управляемым объектом. но зачем тогда использовать указатели? а когда можно использовать оба подхода взаимозаменяемо?

Ответы [ 4 ]

8 голосов
/ 01 декабря 2010

IntPtr нельзя использовать в качестве замены указателя.

IntPtr содержит только числовое значение, поэтому вы не можете использовать его для доступа к каким-либо данным.Отсюда и название;это целочисленное значение с тем же размером, что и указатель.Вам нужно превратить значение в указатель, чтобы получить доступ к данным, на которые оно указывает, поэтому невозможно получить доступ к данным без использования небезопасного кода.

Обратите также внимание, что IntPtr является структурой, а необъект, поэтому сборщик мусора не имеет к нему никакого отношения.

7 голосов
/ 01 декабря 2010

Интерфейс командной строки различает управляемые и неуправляемые указатели. Управляемый указатель набирается, тип указываемого значения известен во время выполнения, и разрешены только безопасные для типов назначения. Неуправляемые указатели можно напрямую использовать только на языке, который их поддерживает, C ++ / CLI - лучший пример.

Эквивалентом неуправляемого указателя на языке C # является IntPtr. Вы можете свободно конвертировать указатель вперед и назад с помощью приведения. С ним не связан ни один тип указателя, хотя его имя звучит как «указатель на int», это эквивалент void* в C / C ++. Для использования такого указателя требуется pinvoke, класс Marshal или приведение к типу управляемого указателя.

Код для игры:

using System;
using System.Runtime.InteropServices;

unsafe class Program {
    static void Main(string[] args) {
        int variable = 42;
        int* p = &variable;
        Console.WriteLine(*p);
        IntPtr raw = (IntPtr)p;
        Marshal.WriteInt32(raw, 666);
        p = (int*)raw;
        Console.WriteLine(*p);
        Console.ReadLine();
    }
}

Обратите внимание, как здесь подходит ключевое слово unsafe. Вы можете позвонить Marshal.WriteInt64 (), и вы не получите никаких жалоб. Это повреждает кадр стека.

6 голосов
/ 01 декабря 2010

IntPtr - это управляемый объект, но объект, на который он указывает, по-прежнему не является сборщиком мусора.Использование небезопасных указателей в C # - это то, чего вам следует избегать.Код, использующий небезопасные указатели, может не учитывать различия в адресах памяти между системами x86 и x64.Он позволяет вам легко манипулировать адресами памяти, что не так с IntPtr, так как вам нужно будет выполнить маршалинг между указателем и фактической структурой, хранящейся по этому адресу памяти.С небезопасными указателями вы можете напрямую работать с базовым типом: вот сообщение в блоге , которое я написал, иллюстрирующее одно возможное использование небезопасных указателей.Другой распространенный пример - непосредственное управление пикселями изображения .

3 голосов
/ 07 апреля 2012

Разыменование данных, на которые указывает IntPtr, заключается в том, что это просто вставляет номер IntPtr в адрес небезопасного ptr, как показано ниже

unsafe{

IntPtr p = new MyStruct("fred");    

myStruct * sptr;

sptr=p;

Console.WriteLine(*sptr->name);

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...