2010-11-30 21 views
7

esta es la segunda parte de la primera cuestión using c# pointersC# punteros vs IntPtr

tan punteros en C# no son recomendables y no gestionada por el recolector de basura, mientras que un IntPtr es un objeto gestionado. pero, ¿por qué usar punteros entonces? y cuando es posible usar ambos enfoques de manera intercambiable?

+9

Tenga en cuenta 'IntPtr' no es más que un tipo de datos primitivo en .NET que está diseñado para contener una dirección. Básicamente es simplemente un 'int' que es 32 bits en una máquina de 32 bits y 64 bits en una máquina de 64 bits. Nada acerca de 'IntPtr' en sí mismo es específico para los punteros. –

Respuesta

7

La CLI distingue entre punteros gestionados y no gestionados. Se escribe un puntero administrado, el tipo de valor apuntado es conocido por el tiempo de ejecución y solo se permiten las asignaciones seguras. Los punteros no administrados solo se pueden usar directamente en un lenguaje que los admite, C++/CLI es el mejor ejemplo.

El equivalente de un puntero no administrado en el lenguaje C# es IntPtr. Puede convertir libremente un puntero hacia adelante y hacia atrás con un molde. No se asocia ningún tipo de puntero aunque su nombre suena como "puntero a int", es el equivalente de void* en C/C++. El uso de dicho puntero requiere pinvoke, la clase Marshal o un lanzamiento a un tipo de puntero administrado.

algo de código para jugar con:

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

Nota cómo la palabra clave unsafe es apropiado en este caso. Puede llamar a Marshal.WriteInt64() y no recibirá ninguna queja en absoluto. Corrompe el marco de la pila.

+2

Esa no es la diferencia entre un puntero y un 'IntPtr'.No es necesario escribir un puntero, también puede ser un puntero sin tipo, es decir, un 'void *'. La diferencia es que un 'IntPtr' no es un puntero en absoluto. – Guffa

5

IntPtr es un objeto administrado pero el objeto al que apunta no es aún basura. Usar punteros inseguros en C# es realmente algo que debes evitar. El código que utiliza punteros inseguros podría no tener en cuenta las diferencias en las direcciones de memoria entre los sistemas x86 y x64. Le permite manipular direcciones de memoria directamente, lo cual no es el caso con IntPtr, ya que necesitaría alinearse entre el puntero y la estructura real almacenada en esta dirección de memoria. Con punteros inseguros, puede trabajar directamente con el tipo subyacente: he aquí un blog post que escribí ilustrando un posible uso de punteros inseguros. Otro ejemplo común es manipulating image pixels directamente.

7

Un IntPtr no se puede utilizar como sustituto de un puntero.

El IntPtr solo contiene un valor numérico, por lo que no puede usarlo para acceder a ningún dato. De ahí el nombre; es un valor entero con el mismo tamaño que un puntero. Debe convertir el valor en un puntero para acceder a los datos a los que apunta, por lo que no hay forma de acceder a los datos sin utilizar un código inseguro.

Tenga en cuenta también que IntPtr es una estructura, no un objeto, por lo que el recolector de basura no se ocupa directamente de ello.

+1

, de hecho, está utilizando Marshalling –

+2

@ Ali Tarhini: eso es simplemente llamar a un método que utiliza un código no seguro para usted. El punto es que el código inseguro debe ser utilizado al final, de lo contrario no hay forma de acceder a los datos. – Guffa

+0

¿Por qué el voto a favor? Si no explica qué es lo que cree que está mal, no puede mejorar la respuesta. – Guffa

2

datos de eliminación de referencias señaladas por un IntPtr es esto simplemente pegando el número de la IntPtr en la dirección de una PTR inseguro como a continuación