Al usar IntelliSense y mirar el código de otras personas, me he encontrado con este IntPtr
tipo; Cada vez que ha sido necesario utilizarlo, simplemente puse null
o IntPtr.Zero
encontré la mayoría de las funciones para trabajar. ¿Qué es exactamente y cuándo / por qué se usa?
171
IntPtr
tiene mucho sentido, porque es un entero (como en un entero matemático) y un puntero (como en un puntero). LaInt
parte tiene poco que ver con el tipo int: es un concepto, no un tipo específico. Aunque para ser justos, lo único que dice la especificación CLI al respecto es que, de hecho, es un "tamaño entero, nativo". Oh bueno :)Es un tipo de valor lo suficientemente grande como para almacenar una dirección de memoria como se usa en código nativo o inseguro, pero no se puede usar directamente como una dirección de memoria en un código administrado seguro.
Puede
IntPtr.Size
averiguar si está ejecutando un proceso de 32 bits o de 64 bits, ya que será de 4 u 8 bytes, respectivamente.fuente
IntPtr
también se usa para representar identificadores que son de 32 bits independientemente de la arquitectura (aunqueSize
todavía dice 8 en ese caso). La especificación de CLI solo señala que es un número entero que es de "tamaño nativo", pero eso no dice mucho, en realidad.Aquí hay un ejemplo:
Estoy escribiendo un programa C # que interactúa con una cámara de alta velocidad. La cámara tiene su propio controlador que adquiere imágenes y las carga automáticamente en la memoria de la computadora.
Entonces, cuando estoy listo para traer la última imagen a mi programa para trabajar, el controlador de la cámara me proporciona un IntPtr donde la imagen YA está almacenada en la memoria física, para que no tenga que perder tiempo / recursos creando otro bloque de memoria para almacenar una imagen que ya está en memoria. IntPtr solo me muestra dónde está la imagen.
fuente
Una interpretación directa
Un IntPtr es un número entero que tiene el mismo tamaño que un puntero .
Puede usar IntPtr para almacenar un valor de puntero en un tipo sin puntero. Esta característica es importante en .NET ya que el uso de punteros es muy propenso a errores y, por lo tanto, es ilegal en la mayoría de los contextos. Al permitir que el valor del puntero se almacene en un tipo de datos "seguro", la plomería entre segmentos de código inseguro se puede implementar en un código de alto nivel más seguro, o incluso en un lenguaje .NET que no admita directamente punteros.
El tamaño de IntPtr es específico de la plataforma, pero este detalle rara vez necesita ser considerado, ya que el sistema usará automáticamente el tamaño correcto.
El nombre "IntPtr" es confuso, algo así
Handle
podría haber sido más apropiado. Mi conjetura inicial fue que "IntPtr" era un puntero a un número entero. La documentación de MSDN de IntPtr entra en detalles algo crípticos sin proporcionar mucha información sobre el significado del nombre.Una perspectiva alternativa
Un
IntPtr
es un puntero con dos limitaciones:En otras palabras, un
IntPtr
es como unvoid*
- pero con la característica adicional de que puede (pero no debe) usarse para la aritmética básica del puntero.Para desreferenciar un
IntPtr
, puede convertirlo en un puntero verdadero (una operación que solo se puede realizar en contextos "inseguros") o puede pasarlo a una rutina auxiliar como las proporcionadas por laInteropServices.Marshal
clase. Usar laMarshal
clase da la ilusión de seguridad ya que no requiere que estés en un contexto explícito "inseguro". Sin embargo, no elimina el riesgo de estrellarse que es inherente al uso de punteros.fuente
¿Qué es un puntero?
En todos los idiomas, un puntero es un tipo de variable que almacena una dirección de memoria, y puede pedirles que le digan la dirección a la que apuntan o el valor de la dirección a la que apuntan.
Un puntero puede considerarse como una especie de marca de libro. Excepto que, en lugar de usarse para saltar rápidamente a una página de un libro, se usa un puntero para realizar un seguimiento o mapear bloques de memoria.
Imagine la memoria de su programa precisamente como una gran matriz de 65535 bytes.
Los punteros apuntan obedientemente
Los punteros recuerdan una dirección de memoria cada uno y, por lo tanto, cada uno apunta a una única dirección en la memoria.
Como grupo, los punteros recuerdan y recuerdan direcciones de memoria, obedeciendo cada comando hasta la saciedad.
Eres su rey
Punteros en C #
También específicos de C #, los punteros son de tipo int y, por lo tanto, están firmados.
Sin embargo, no puede usar direcciones numeradas negativamente, tampoco puede acceder a una dirección superior a 65534. Cualquier intento de hacerlo arrojará una excepción System.AccessViolationException.
Un puntero llamado MyPointer se declara así:
Un puntero en C # es un int, pero las direcciones de memoria en C # comienzan en 0 y se extienden hasta 65534.
Las cosas puntiagudas deben manejarse con especial cuidado
La palabra inseguro tiene la intención de asustarlo, y por una muy buena razón: los punteros son cosas puntiagudas, y las cosas puntiagudas, por ejemplo, espadas, hachas, punteros, etc., deben manejarse con especial cuidado.
Los punteros le dan al programador un control estricto de un sistema. Por lo tanto, es probable que los errores cometidos tengan consecuencias más graves.
Para usar punteros, el código inseguro debe estar habilitado en las propiedades de su programa, y los punteros deben usarse exclusivamente en métodos o bloques marcados como inseguros.
Ejemplo de un bloque inseguro
Cómo usar punteros
Cuando las variables u objetos se declaran o instancian, se almacenan en la memoria.
int *MyPointer;
MyPointer = &MyVariable;
Una vez que se asigna una dirección a un puntero, se aplica lo siguiente:
MyPointer = &MyVariable; // Set MyPointer to point at MyVariable
"MyPointer is pointing at " + *MyPointer;
Como un puntero es una variable que contiene una dirección de memoria, esta dirección de memoria se puede almacenar en una variable de puntero.
Ejemplo de punteros utilizados con cuidado y responsabilidad
Observe que el tipo del puntero es un int. Esto se debe a que C # interpreta las direcciones de memoria como números enteros (int).
¿Por qué es int en lugar de uint?
No hay una buena razón.
¿Por qué usar punteros?
Los punteros son muy divertidos. Con gran parte de la computadora controlada por la memoria, los punteros le otorgan a un programador mayor control de la memoria de su programa.
Monitoreo de memoria.
Use punteros para leer bloques de memoria y monitorear cómo los valores apuntados cambian con el tiempo.
Cambie estos valores de manera responsable y realice un seguimiento de cómo afectan sus cambios a su computadora.
fuente
65534
parece muy incorrecto como un rango de puntero. Debes proporcionar una referencia.System.IntPtr
. Me gustaría ver la respuesta actualizada al final explicando qué es tambiénSystem.IntPtr
y cómo se relaciona con los punteros inseguros en C #, por favor.MSDN nos dice:
http://msdn.microsoft.com/en-us/library/system.intptr(VS.71).aspx
fuente
Bueno, esta es la página de MSDN que trata
IntPtr
.La primera línea dice:
En cuanto a qué puntero o identificador es, la página continúa:
Un puntero es una referencia a un área de memoria que contiene algunos datos que le interesan.
Un identificador puede ser un identificador para un objeto y se pasa entre métodos / clases cuando ambos lados necesitan acceder a ese objeto.
fuente
Un
IntPtr
es un tipo de valor que se utiliza principalmente para contener direcciones de memoria o identificadores. Un puntero es una dirección de memoria. Un puntero se puede escribir (por ejemploint*
) o sin escribir (por ejemplovoid*
). Un identificador de Windows es un valor que generalmente es del mismo tamaño (o más pequeño) que una dirección de memoria y representa un recurso del sistema (como un archivo o ventana).fuente