Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/280.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将偏移量添加到IntPtr_C#_.net_Pinvoke_Interop - Fatal编程技术网

C# 将偏移量添加到IntPtr

C# 将偏移量添加到IntPtr,c#,.net,pinvoke,interop,C#,.net,Pinvoke,Interop,我正在寻找一种特别是在C#或.NET中执行指针操作的方法 我想做一些非常简单的事情 有一个指针IntPtr,我想得到指向前面2个字节的IntPtr对象 我读了一些帖子,说这个愚蠢的片段会有用 IntPtr ptr = new IntPtr(oldptr.ToInt32() + 2); 但我怀疑这句话是否也适用于64位机器(因为寻址是64位的) 我发现这个优雅的方法可以添加偏移量,但不幸的是,它只在.NET 4.0中使用我建议您使用ToInt64()和long来执行计算。通过这种方式,您将避免在

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

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

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

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

IntPtr ptr = new IntPtr(oldptr.ToInt32() + 2);
但我怀疑这句话是否也适用于64位机器(因为寻址是64位的)


我发现这个优雅的方法可以添加偏移量,但不幸的是,它只在.NET 4.0中使用

我建议您使用ToInt64()和long来执行计算。通过这种方式,您将避免在64位版本的.NET framework上出现问题

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

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

您可以使用扩展方法:

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

对于C#中的指针算法,您应该在
不安全的
上下文中使用适当的指针:

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

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

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

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

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

公共静态类intptrex
{
#区域方法:算术
公共静态IntPtr递减(此IntPtr指针,Int32值)
{
返回增量(指针,-值);
}
公共静态IntPtr递减(此IntPtr指针,Int64值)
{
返回增量(指针,-值);
}
公共静态IntPtr递减(此IntPtr指针,IntPtr值)
{
交换机(IntPtr.Size)
{
案例大小(Int32):
返回(新的IntPtr(指针.ToInt32()-value.ToInt32());
违约:
返回(新的IntPtr(指针.ToInt64()-value.ToInt64());
}
}
公共静态IntPtr增量(此IntPtr指针,Int32值)
{
未经检查
{
交换机(IntPtr.Size)
{
案例大小(Int32):
返回(新的IntPtr(指针.ToInt32()+值));
违约:
返回(新的IntPtr(指针.ToInt64()+值));
}
}
}
公共静态IntPtr增量(此IntPtr指针,Int64值)
{
未经检查
{
交换机(IntPtr.Size)
{
案例大小(Int32):
返回(新的IntPtr((Int32)(pointer.ToInt32()+值));
违约:
返回(新的IntPtr(指针.ToInt64()+值));
}
}
}
公共静态IntPtr增量(此IntPtr指针,IntPtr值)
{
未经检查
{
交换机(IntPtr.Size)
{
案例大小(整数):
返回新的IntPtr(指针.ToInt32()+值.ToInt32());
违约:
返回新的IntPtr(指针.ToInt64()+值.ToInt64());
}
}
}
#端区
#区域方法:比较
公共静态Int32比较(此IntPtr左,Int32右)
{
返回左。比较((UInt32)右);
}
公共静态Int32比较(此IntPtr左,IntPtr右)
{
if(left.ToUInt64()>right.ToUInt64())
返回1;
if(left.ToUInt64()right)
返回1;
if(left.ToUInt64()=0);
}
公共静态布尔LessThanOrEqualTo(此IntPtr左,IntPtr右)
{

返回(左。比较到(右)在64位计算机上,一个字节仍然是一个字节。因此,它仍然会向前跳过两个字节。@dan:是的,但字节的地址可能超出32位范围!Marcin认为这对于64位无效是正确的。+1表示实指针算术,而不是滥用整数ALU来执行地址计算。现在Microsoft in.NET 4具有introduced IntPtr.Add返回“一个新指针,它反映了指针的偏移量的增加”,这使得IntPtr对于指针运算非常方便,并且似乎表明Microsoft希望使用它。使用不安全代码存在限制-因此在编译过程中需要/unsafe标志。如果可能,最好避免使用/unsafe标志。还值得注意的是,ALU用于计算地址,无论使用何种方法你使用。我看不出它是如何通过手工计算被“滥用”的。不管这是什么样的静态。对不起,我刚刚通过对这个答案进行投票,破坏了你的满分1000分;/这怎么不是最好的答案……也许加上一些注释,但代码说明了这一点
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
}