2009-12-08 36 views
31

Tôi đang tìm cách thực hiện các thao tác con trỏ trong C# hoặc .NET nói riêng.Thêm bù đắp vào IntPtr

tôi muốn làm một cái gì đó rất đơn giản

Có một con trỏ IntPtr Tôi muốn có được đối tượng IntPtr mà chỉ vào 2 byte ở phía trước.

Tôi đọc một số bài thật kỹ xem mã foolowing sẽ làm việc ...

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

Nhưng tôi có nghi ngờ cho dù tuyên bố này cũng có giá trị trong máy 64-bit (kể từ khi giải quyết là trong 64-bit có). .

tôi thấy phương pháp đơn giản này để thêm bù đắp, nhưng tiếc là trong .NET 4.0 http://msdn.microsoft.com/en-us/library/system.intptr.add%28VS.100%29.aspx

+0

Một byte vẫn là một byte trên 64-bit-máy. Vì vậy, nó vẫn sẽ bỏ qua hai byte về phía trước. –

+1

@dan: có, nhưng địa chỉ của byte có thể nằm ngoài phạm vi 32 bit! Marcin là chính xác rằng điều này là không hợp lệ cho 64-bit. – Lucero

Trả lời

33

tôi đề nghị bạn sử dụng ToInt64() và thời gian để thực hiện các tính toán của bạn. Bằng cách này bạn sẽ tránh được vấn đề trên phiên bản 64 bit của khung công tác .NET.

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

Điều này thêm một chút phí trên hệ thống 32 bit, nhưng an toàn hơn.

1

Bạn có thể sử dụng một phương pháp khuyến nông:

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); 
9

Đối với con trỏ số học trong C# bạn nên sử dụng con trỏ thích hợp bên trong một unsafe bối cảnh:

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

Loại IntPtr là để thông qua xung quanh xử lý hoặc con trỏ và cũng cho marshalling ngôn ngữ hỗ trợ con trỏ. Nhưng nó không phải cho số học con trỏ.

+1

+1 cho số học con trỏ thực thay vì lạm dụng ALU số nguyên để thực hiện các phép tính địa chỉ. – Frank

+5

Bây giờ Microsoft trong .NET 4 đã giới thiệu IntPtr.Add trả về "Một con trỏ mới phản ánh việc bổ sung bù cho con trỏ", điều này làm cho IntPtr thuận tiện cho số học con trỏ, và dường như chỉ ra rằng Microsoft hy vọng nó được sử dụng cho . – Spike0xff

8

Tôi thấy rằng tôi có thể tránh hoạt động của con trỏ bằng cách sử dụng các phương thức Marshal.ReadByte(), Marshal.ReadInt16() vv. Nhóm phương pháp này cho phép xác định bù đắp trong việc releation cho IntPtr ...

4
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 
} 
+1

Làm thế nào đây không phải là câu trả lời hay nhất ... Có lẽ thêm một số bình luận, nhưng mã nói cho chính nó ... – DeeJayh

Các vấn đề liên quan