Dirección de memoria C # y variable

en C #, ¿hay alguna manera de

  1. Obtener la dirección de memoria almacenada en una variable de tipo de referencia?
  2. Obtener la dirección de memoria de una variable?

EDITAR:

int i; int* pi = &i; 
  • ¿Cómo se imprime el valor hexadecimal de pi?

Para el n. ° 2, el operador & trabajará de la misma manera que en C. Si la variable no está en la stack, es posible que necesite usar una instrucción fixed para fijarla mientras trabaja para que el recolector de basura no la mueva, aunque.

Para el n. ° 1, los tipos de referencia son más complicados: necesitará usar un GCHandle , y el tipo de referencia debe ser blittable, es decir, tener un diseño de memoria definido y poder ser copiado en modo bit.

Para acceder a la dirección como un número, puede convertir desde el tipo de puntero a IntPtr (un tipo de entero definido para ser del mismo tamaño que un puntero), y desde allí a uint o ulong (dependiendo del tamaño del puntero de la máquina subyacente) )

 using System; using System.Runtime.InteropServices; [StructLayout(LayoutKind.Sequential)] class Blittable { int x; } class Program { public static unsafe void Main() { int i; object o = new Blittable(); int* ptr = &i; IntPtr addr = (IntPtr)ptr; Console.WriteLine(addr.ToString("x")); GCHandle h = GCHandle.Alloc(o, GCHandleType.Pinned); addr = h.AddrOfPinnedObject(); Console.WriteLine(addr.ToString("x")); h.Free(); } } 

El número 1 no es posible en absoluto, no puede tener un puntero a un objeto administrado. Sin embargo, puede usar una estructura IntPtr para obtener información sobre la dirección del puntero en la referencia:

 GCHandle handle = GCHandle.Alloc(str, GCHandleType.Pinned); IntPtr pointer = GCHandle.ToIntPtr(handle); string pointerDisplay = pointer.ToString(); handle.Free(); 

Para el número 2, usa el operador &:

 int* p = &myIntVariable; 

Los apuntadores, por supuesto, tienen que hacerse en un bloque inseguro, y debe permitir código inseguro en la configuración del proyecto. Si la variable es una variable local en un método, está asignada en la stack por lo que ya está fija, pero si la variable es un miembro de un objeto, debe fijar ese objeto en la memoria utilizando la palabra clave fixed para que no se mueva. el recolector de basura.

Para responder a tu pregunta más correctamente:

# 1 es posible pero un poco complicado, y solo debería hacerse por razones de depuración:

 object o = new object(); TypedReference tr = __makeref(o); IntPtr ptr = **(IntPtr**)(&tr); 

Esto funciona para cualquier objeto y realmente devuelve el puntero interno al objeto en la memoria. Recuerde que la dirección puede cambiar en cualquier momento debido al GC, que le gusta mover objetos a través de la memoria.

# 2 Los punteros no son objetos y, por lo tanto, no heredan ToString de ellos. Tienes que lanzar el puntero a IntPtr así:

 Console.WriteLine((IntPtr)pi);