Что такое IntPtr?

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

8 ответов

Решение

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

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

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

Вот пример:

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

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

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

IntPtr - это целое число того же размера, что и указатель.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Вы их король.

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

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

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

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

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

int * MyPointer;

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

Остроконечные вещи должны обрабатываться с особой тщательностью

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

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

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

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

unsafe
{
    // Place code carefully and responsibly here.

}

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

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

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

int *MyPointer;

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

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?

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

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

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

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

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

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

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

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

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

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

Что касается указателя или дескриптора, то страница переходит в состояние:

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

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

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

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

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

Другие вопросы по тегам