C# 向 IntPtr 添加偏移量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1866236/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 21:29:15  来源:igfitidea点击:

Add offset to IntPtr

c#.netpinvokeinterop

提问by Marcin Rybacki

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

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

I want to do something very simple

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

Having a pointer IntPtr I want to get IntPtr object which points to 2 bytes ahead.

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

I read some post that the foolowing snippet will work...

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

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

But I have doubts whether this statement is also valid for 64-bit machine (since addressing is in 64-bits there)..

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

I found this elegant method to add offset, but unfortunately is in .NET 4.0 only http://msdn.microsoft.com/en-us/library/system.intptr.add%28VS.100%29.aspx

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

采纳答案by Laurent Etiemble

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.

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

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

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

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

回答by TcKs

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

回答by Joey

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

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

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

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

回答by Marcin Rybacki

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...

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

回答by BLeB

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

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

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

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

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

回答by Tommaso Belluzzo

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
}