Añadir desplazamiento a IntPtr

Estoy buscando una forma de realizar operaciones de puntero en C # o .NET en particular.

Quiero hacer algo muy simple

Tener un puntero IntPtr Quiero obtener el objeto IntPtr que apunta a 2 bytes más adelante.

Leí una publicación que dice que el fragmento de engaño funcionará …

IntPtr ptr = new IntPtr(oldptr.ToInt32() + 2); 

Pero tengo dudas de si esta statement también es válida para la máquina de 64 bits (ya que el direccionamiento está en 64 bits).

Encontré este elegante método para agregar compensación, pero desafortunadamente solo está en .NET 4.0 http://msdn.microsoft.com/en-us/library/system.intptr.add%28VS.100%29.aspx

Le sugiero que use ToInt64 () y mucho tiempo para realizar su cálculo. De esta forma evitará el problema en la versión de 64 bits del .NET framework.

 IntPtr ptr = new IntPtr(oldptr.ToInt64() + 2); 

Esto agrega un poco de sobrecarga en el sistema de 32 bits, pero es más seguro.

En .NET 4, se agregaron los métodos static Add () y Subtract ().

 IntPtr ptr = IntPtr.Add(oldPtr, 2); 

http://msdn.microsoft.com/en-us/library/system.intptr.add.aspx

Para la aritmética del puntero en C #, debe usar punteros apropiados dentro de un contexto unsafe :

 class PointerArithmetic { unsafe static void Main() { int* memory = stackalloc int[30]; long* difference; int* p1 = &memory[4]; int* p2 = &memory[10]; difference = (long*)(p2 - p1); System.Console.WriteLine("The difference is: {0}", (long)difference); } } 

El tipo IntPtr es para pasar mangos o punteros y también para organizar los idiomas que admiten punteros. Pero no es para la aritmética del puntero.

Descubrí que puedo evitar las operaciones del puntero usando los métodos Marshal.ReadByte (), Marshal.ReadInt16 () etc. Este grupo de métodos permite especificar el desplazamiento en releation a IntPtr …

 public static class IntPtrExtensions { #region Methods: Arithmetics public static IntPtr Decrement(this IntPtr pointer, Int32 value) { return Increment(pointer, -value); } public static IntPtr Decrement(this IntPtr pointer, Int64 value) { return Increment(pointer, -value); } public static IntPtr Decrement(this IntPtr pointer, IntPtr value) { switch (IntPtr.Size) { case sizeof(Int32): return (new IntPtr(pointer.ToInt32() - value.ToInt32())); default: return (new IntPtr(pointer.ToInt64() - value.ToInt64())); } } public static IntPtr Increment(this IntPtr pointer, Int32 value) { unchecked { switch (IntPtr.Size) { case sizeof(Int32): return (new IntPtr(pointer.ToInt32() + value)); default: return (new IntPtr(pointer.ToInt64() + value)); } } } public static IntPtr Increment(this IntPtr pointer, Int64 value) { unchecked { switch (IntPtr.Size) { case sizeof(Int32): return (new IntPtr((Int32)(pointer.ToInt32() + value))); default: return (new IntPtr(pointer.ToInt64() + value)); } } } public static IntPtr Increment(this IntPtr pointer, IntPtr value) { unchecked { switch (IntPtr.Size) { case sizeof(int): return new IntPtr(pointer.ToInt32() + value.ToInt32()); default: return new IntPtr(pointer.ToInt64() + value.ToInt64()); } } } #endregion #region Methods: Comparison public static Int32 CompareTo(this IntPtr left, Int32 right) { return left.CompareTo((UInt32)right); } public static Int32 CompareTo(this IntPtr left, IntPtr right) { if (left.ToUInt64() > right.ToUInt64()) return 1; if (left.ToUInt64() < right.ToUInt64()) return -1; return 0; } public static Int32 CompareTo(this IntPtr left, UInt32 right) { if (left.ToUInt64() > right) return 1; if (left.ToUInt64() < right) return -1; return 0; } #endregion #region Methods: Conversion public unsafe static UInt32 ToUInt32(this IntPtr pointer) { return (UInt32)((void*)pointer); } public unsafe static UInt64 ToUInt64(this IntPtr pointer) { return (UInt64)((void*)pointer); } #endregion #region Methods: Equality public static Boolean Equals(this IntPtr pointer, Int32 value) { return (pointer.ToInt32() == value); } public static Boolean Equals(this IntPtr pointer, Int64 value) { return (pointer.ToInt64() == value); } public static Boolean Equals(this IntPtr left, IntPtr ptr2) { return (left == ptr2); } public static Boolean Equals(this IntPtr pointer, UInt32 value) { return (pointer.ToUInt32() == value); } public static Boolean Equals(this IntPtr pointer, UInt64 value) { return (pointer.ToUInt64() == value); } public static Boolean GreaterThanOrEqualTo(this IntPtr left, IntPtr right) { return (left.CompareTo(right) >= 0); } public static Boolean LessThanOrEqualTo(this IntPtr left, IntPtr right) { return (left.CompareTo(right) <= 0); } #endregion #region Methods: Logic public static IntPtr And(this IntPtr pointer, IntPtr value) { switch (IntPtr.Size) { case sizeof(Int32): return (new IntPtr(pointer.ToInt32() & value.ToInt32())); default: return (new IntPtr(pointer.ToInt64() & value.ToInt64())); } } public static IntPtr Not(this IntPtr pointer) { switch (IntPtr.Size) { case sizeof(Int32): return (new IntPtr(~pointer.ToInt32())); default: return (new IntPtr(~pointer.ToInt64())); } } public static IntPtr Or(this IntPtr pointer, IntPtr value) { switch (IntPtr.Size) { case sizeof(Int32): return (new IntPtr(pointer.ToInt32() | value.ToInt32())); default: return (new IntPtr(pointer.ToInt64() | value.ToInt64())); } } public static IntPtr Xor(this IntPtr pointer, IntPtr value) { switch (IntPtr.Size) { case sizeof(Int32): return (new IntPtr(pointer.ToInt32() ^ value.ToInt32())); default: return (new IntPtr(pointer.ToInt64() ^ value.ToInt64())); } } #endregion } 

Puedes usar un método de extensión:

 public static IntPtrExtensions { public static IntPtr Add( this IntPtr ptr, int offSet ) { IntPtr ret = new IntPtr( ptr.ToInt64() + offSet ); return ret; } } // ... somewhere else ... IntPtr pointer = GetHandle().Add( 15 );