Что такое IntPtr? - PullRequest
       21

Что такое IntPtr?

159 голосов
/ 18 июля 2009

Используя IntelliSense и просматривая чужой код, я натолкнулся на этот тип IntPtr; каждый раз, когда его нужно было использовать, я просто помещал null или IntPtr.Zero и обнаруживал, что большинство функций работают. Что именно и когда / почему он используется?

Ответы [ 8 ]

149 голосов
/ 18 июля 2009

Это "родное (зависящее от платформы) целое число размера". Он внутренне представлен как void*, но представлен как целое число. Вы можете использовать его всякий раз, когда вам нужно сохранить неуправляемый указатель и вы не хотите использовать код unsafe. IntPtr.Zero эффективно NULL (нулевой указатель).

61 голосов
/ 18 июля 2009

Это тип значения, достаточно большой для хранения адреса памяти, который используется в собственном или небезопасном коде, но не может напрямую использоваться в качестве адреса памяти в безопасном управляемом коде.

Вы можете использовать IntPtr.Size, чтобы узнать, выполняете ли вы 32-битный или 64-битный процесс, так как он будет 4 или 8 байтов соответственно.

40 голосов
/ 18 июля 2009

Вот пример:

Я пишу программу на C #, которая взаимодействует с высокоскоростной камерой. У камеры есть собственный драйвер, который автоматически получает изображения и загружает их в память компьютера.

Таким образом, когда я готов принести в свою программу последнее изображение для работы, драйвер камеры предоставляет мне IntPtr для того, где изображение УЖЕ хранится в физической памяти, поэтому мне не нужно тратить время ресурсы, создающие другой блок памяти для хранения изображения, которое уже находится в памяти. IntPtr просто показывает мне, где изображение уже есть.

32 голосов
/ 01 ноября 2009

Прямая интерпретация

IntPtr - это целое число , равное размеру указателя .

Вы можете использовать IntPtr для хранения значения указателя в типе без указателя. Эта функция важна в .NET, так как использование указателей очень подвержено ошибкам и поэтому в большинстве случаев недопустимо. Позволяя хранить значение указателя в «безопасном» типе данных, прокладка между небезопасными сегментами кода может быть реализована в более безопасном высокоуровневом коде - или даже в языке .NET, который не имеет прямого отношения указатели поддержки.

Размер IntPtr зависит от платформы, но эту деталь редко нужно учитывать, поскольку система автоматически использует правильный размер.

Название «IntPtr» сбивает с толку - что-то вроде Handle могло бы быть более подходящим. Первоначально я предполагал, что IntPtr - это указатель от до целого числа. Документация MSDN для IntPtr раскрывает некоторые загадочные подробности, не давая много понимания смысла имени.

Альтернативная перспектива

IntPtr - указатель с двумя ограничениями:

  1. Он не может быть напрямую разыменован
  2. Он не знает тип данных, на которые он указывает.

Другими словами, IntPtr подобен void* - но с дополнительной функцией, которую он может (но не должен) использовать для базовой арифметики указателей.

Чтобы разыменовать IntPtr, вы можете либо привести его к истинному указателю (операция, которая может быть выполнена только в «небезопасных» контекстах), либо передать его вспомогательной подпрограмме, например, предоставляемой InteropServices.Marshal класс. Использование класса Marshal создает иллюзию безопасности, поскольку не требует, чтобы вы находились в явном «небезопасном» контексте. Тем не менее, он не устраняет риск сбоя, который присущ указателям.

13 голосов
/ 13 сентября 2016

Что такое указатель?

Во всех языках указатель является типом переменной, в которой хранится адрес памяти, и вы можете либо попросить их сообщить вам адрес , на который они указывают, либо значение по адресу они указывают на.

Указатель можно рассматривать как своего рода закладку. За исключением того, что вместо быстрого перехода к странице в книге используется указатель для отслеживания или отображения блоков памяти.

Представьте себе память вашей программы в точности как один большой массив из 65535 байтов.

Указатели послушно указывают

Указатели запоминают по одному адресу памяти каждый, и поэтому каждый из них указывает на один адрес в памяти.

Как группа, указатели запоминают и запоминают адреса памяти, подчиняясь каждой вашей команде до тошноты.

Вы их король.

Указатели на C #

В частности, в C # указатель является целочисленной переменной, которая хранит адрес памяти в диапазоне от 0 до 65534.

Также специфично для C #, указатели имеют тип int и поэтому подписаны.

Вы не можете использовать адреса с отрицательной нумерацией, а также не можете получить доступ к адресу выше 65534. Любая попытка сделать это вызовет исключение System.AccessViolationException.

Указатель с именем MyPointer объявлен так:

int * MyPointer;

Указатель в C # является целым числом, но адреса памяти в C # начинаются с 0 и простираются до 65534.

С острыми предметами следует обращаться с особой тщательностью

Слово «небезопасно» - это , предназначенное для того, чтобы напугать вас, и по очень веской причине: указатели - это заостренные вещи, а заостренные, например с мечами, топорами, указателями и т. д. следует обращаться с особой осторожностью.

Указатели дают программисту жесткий контроль над системой. Поэтому допущенные ошибки могут иметь более серьезные последствия.

Чтобы использовать указатели, небезопасный код должен быть включен в свойствах вашей программы, а указатели должны использоваться исключительно в методах или блоках, помеченных как небезопасные.

Пример небезопасного блока

unsafe
{
    // Place code carefully and responsibly here.

}

Как использовать указатели

Когда переменные или объекты объявляются или создаются, они сохраняются в памяти.

  • Объявление указателя с помощью префикса символа *.

int *MyPointer;

  • Чтобы получить адрес переменной, используйте префикс & символа.

MyPointer = &MyVariable;

Как только адрес назначен указателю, применяется следующее:

  • Без * префикса для обозначения адреса памяти, на который указывает int.

MyPointer = &MyVariable; // Set MyPointer to point at MyVariable

  • С префиксом *, чтобы получить значение, сохраненное по адресу памяти, на который указывает.

"MyPointer is pointing at " + *MyPointer;

Поскольку указатель является переменной, которая содержит адрес памяти, этот адрес памяти может быть сохранен в переменной указателя.

Пример использования указателей осторожно и ответственно

    public unsafe void PointerTest()
    {
        int x = 100; // Create a variable named x

        int *MyPointer = &x; // Store the address of variable named x into the pointer named MyPointer

        textBox1.Text = ((int)MyPointer).ToString(); // Displays the memory address stored in pointer named MyPointer

        textBox2.Text = (*MyPointer).ToString(); // Displays the value of the variable named x via the pointer named MyPointer.

    }

Обратите внимание, что тип указателя - int. Это связано с тем, что C # интерпретирует адреса памяти как целые числа (int).

Почему это int вместо uint?

Нет веской причины.

Зачем использовать указатели?

Указатели очень веселые. Так как большая часть компьютера управляется памятью, указатели дают программисту больше контроля над памятью их программ.

Мониторинг памяти.

Используйте указатели для чтения блоков памяти и отслеживания изменения значений, на которые указывают значения.

Измените эти значения ответственно и следите за тем, как ваши изменения влияют на ваш компьютер.

7 голосов
/ 18 июля 2009

MSDN сообщает нам:

Тип IntPtr предназначен для целое число, размер которого платформы. То есть ожидается, что экземпляр этого типа быть 32-битным на 32-битном оборудовании и операционные системы и 64-битные на 64-битное оборудование и операционные системы.

Тип IntPtr может использоваться языки, которые поддерживают указатели, и как общее средство обращения к данным между языками, которые делают и не делают указатели поддержки.

Объекты IntPtr также можно использовать для держись за ручки. Например, случаи IntPtr широко используются в Класс System.IO.FileStream для хранения файловые дескрипторы.

Тип IntPtr является CLS-совместимым, в то время как тип UIntPtr - нет. Только тип IntPtr используется в общем язык выполнения. Тип UIntPtr в основном для поддержания архитектурная симметрия с IntPtr типа.

http://msdn.microsoft.com/en-us/library/system.intptr(VS.71).aspx

5 голосов
/ 18 июля 2009

Ну, это страница MSDN , которая имеет дело с IntPtr.

Первая строка гласит:

Платформо-зависимый тип, используемый для представления указателя или дескриптора.

Относительно того, что указатель или дескриптор страницы указывает на:

Тип IntPtr может использоваться языки, которые поддерживают указатели, и как общее средство обращения к данным между языками, которые делают и не делают указатели поддержки.

Объекты IntPtr также можно использовать для держись за ручки. Например, случаи IntPtr широко используются в Класс System.IO.FileStream для хранения файловые дескрипторы.

Указатель - это ссылка на область памяти, в которой хранятся интересующие вас данные.

Дескриптор может быть идентификатором объекта и передается между методами / классами, когда обеим сторонам необходим доступ к этому объекту.

0 голосов
/ 13 января 2019

IntPtr - это тип значения , который в основном используется для хранения адресов или дескрипторов памяти. указатель является адресом памяти. Указатель может быть напечатан (например, int*) или нетипизирован (например, void*). дескриптор Windows - это значение, которое обычно имеет тот же размер (или меньше), что и адрес памяти, и представляет системный ресурс (например, файл или окно).

...