Что такое IntPtr?

146

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

Теги:
intptr

8 ответов

142
Лучший ответ

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

  • 26
    Опять же, что такое указатель?
  • 46
    Указатель - это то, что указывает на адрес в памяти. На управляемых языках у вас есть ссылки (адрес может перемещаться), в то время как на неуправляемых языках у вас есть указатели (адрес фиксированный)
Показать ещё 8 комментариев
58

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

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

  • 14
    Хорошая мысль об определении размера адресного пространства для процесса.
  • 0
    @Noldorin Верно, но не обязательно надежно. В прошлом было много архитектур с несколькими типами указателей, а в Windows IntPtr также используется для представления дескрипторов, которые являются 32-битными независимо от архитектуры (хотя в этом случае Size прежнему имеет значение 8). В спецификации CLI только отмечается, что это целое число «родного размера», но на самом деле это мало что говорит.
Показать ещё 3 комментария
34

Вот пример:

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

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

  • 5
    Таким образом, IntPtr simple позволяет вам использовать неуправляемый указатель (например, используемый в драйвере камеры) в управляемом коде?
  • 3
    Да. В этом случае, скорее всего, драйвер камеры использует неуправляемые драйверы под капотом, но для правильной работы в мире, управляемом только, он предоставляет IntPtr, позволяющий мне безопасно работать с данными.
Показать ещё 1 комментарий
30

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

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

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

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

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

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

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

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

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

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

  • 2
    Есть некоторый прецедент для имени "intptr" из стандарта C99 языка программирования "C". linux.die.net/man/3/intptr_t .
  • 2
    Ссылка на intptr_t на cplusplus.com/reference/cstdint .
11

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

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

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

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

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

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

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

Ты их король.

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

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

Также, для С#, указатели имеют тип int и поэтому подписываются.

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

Указатель, называемый MyPointer, объявляется следующим образом:

int * MyPointer;

Указатель в С# - это int, но адреса памяти в С# начинаются с 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. Это связано с тем, что С# интерпретирует адреса памяти как целые числа (int).

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

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

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

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

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

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

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

  • 2
    65534 кажется очень неправильным в качестве диапазона указателя. Вы должны предоставить ссылку.
  • 1
    Я проголосовал за это, потому что это отличная статья с пояснениями. Я хотел бы видеть некоторые ссылки на спецификации, которые вы упомянули (как прокомментировано выше). Тем не мение; этот ответ не имеет ничего общего с вопросом. Вопрос был о System.IntPtr . Я хотел бы, чтобы ответ обновлялся в конце, объясняя, что такое System.IntPtr и как он связан с небезопасными указателями в C #, пожалуйста.
7

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

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

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

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

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

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

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

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

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

0

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню