Add offset to IntPtr

前端 未结 7 1247
庸人自扰
庸人自扰 2020-11-30 06:59

I\'m looking for a way to perform pointer operations in C# or .NET in particular.

I want to do something very simple

Having a pointer IntPtr I want to get I

相关标签:
7条回答
  • 2020-11-30 07:40

    I found that I can avoid pointer operations by using Marshal.ReadByte(), Marshal.ReadInt16() etc. methods. This group of methods allow to specify offset in releation to the IntPtr...

    0 讨论(0)
  • 2020-11-30 07:46
    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
    }
    
    0 讨论(0)
  • 2020-11-30 07:55

    For pointer arithmetic in C# you should use proper pointers inside an unsafe context:

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

    The IntPtr type is for passing around handles or pointers and also for marshalling to languages that support pointers. But it's not for pointer arithmetic.

    0 讨论(0)
  • 2020-11-30 07:57

    You can use a extension method:

    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 );
    
    0 讨论(0)
  • 2020-11-30 07:59

    I suggest you to use ToInt64() and long to perform your computation. This way you will avoid problem on 64 bits version of the .NET framework.

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

    This add a bit of overhead on 32 bits system, but it is safer.

    0 讨论(0)
  • 2020-11-30 07:59

    In .net 4 static Add() and Subtract() methods have been added.

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

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

    0 讨论(0)
提交回复
热议问题