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);
}