c# указатели против IntPtr

Это 2-я Часть 1-го вопроса использование указателей c#

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

4 ответов


CLI различает управляемые и неуправляемые указатели. Вводится управляемый указатель, тип указанного значения известен среде выполнения и разрешены только безопасные для типов назначения. Неуправляемые указатели могут использоваться только непосредственно на языке, который их поддерживает, 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 ключевое слово здесь уместно. Можешь позвонить маршалу.WriteInt64() и вы получите никаких жалоб. Это портит кадр стека.


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

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

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


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


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

unsafe{

IntPtr p = new MyStruct("fred");    

myStruct * sptr;

sptr=p;

Console.WriteLine(*sptr->name);

}