向IntPtr添加偏移量

Mar*_*cki 36 .net c# pinvoke interop

我正在寻找一种在C#或.NET中执行指针操作的方法.

我想做一些非常简单的事情

有一个指针IntPtr我想获得指向前2个字节的IntPtr对象.

我读了一些帖子,说这个愚蠢的片段会起作用......

IntPtr ptr = new IntPtr(oldptr.ToInt32() + 2);
Run Code Online (Sandbox Code Playgroud)

但我怀疑这个语句是否也适用于64位机器(因为在那里寻址是64位).

我发现这种优雅的方法来添加偏移量,但不幸的是只在.NET 4.0中http://msdn.microsoft.com/en-us/library/system.intptr.add%28VS.100%29.aspx

BLe*_*LeB 45

在.net 4中添加了静态Add()和Subtract()方法.

IntPtr ptr = IntPtr.Add(oldPtr, 2);
Run Code Online (Sandbox Code Playgroud)

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

  • 为什么这是静态的.对不起,我刚刚用这个答案推销了你的满分1000分; / (3认同)

Lau*_*ble 39

我建议你使用ToInt64()和long来执行你的计算.这样您就可以避免在64位版本的.NET框架上出现问题.

IntPtr ptr = new IntPtr(oldptr.ToInt64() + 2);
Run Code Online (Sandbox Code Playgroud)

这在32位系统上增加了一些开销,但它更安全.


Joe*_*oey 9

对于C#中的指针运算,您应该在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);
    }
}
Run Code Online (Sandbox Code Playgroud)

IntPtr类型用于传递句柄或指针,也用于编组支持指针的语言.但它不适用于指针算术.

  • 既然.NET 4中的Microsoft已经引入了IntPtr.Add,它返回"反映向指针添加偏移量的新指针",这使得IntPtr便于指针运算,并且似乎表明Microsoft希望将其用于此. (5认同)

Mar*_*cki 9

我发现我可以通过使用Marshal.ReadByte(),Marshal.ReadInt16()等方法来避免指针操作.这组方法允许指定与IntPtr相关的偏移量...


Tom*_*zzo 7

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
}
Run Code Online (Sandbox Code Playgroud)

  • 这怎么不是最好的答案......也许添加一些评论,但代码不言自明...... (2认同)