Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ssis/2.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#_Memory_Intptr - Fatal编程技术网

C#安全IntPtr铸造

C#安全IntPtr铸造,c#,memory,intptr,C#,Memory,Intptr,问题 哪种类型转换最适合4字节IntPtr(特别是x84应用程序) int:看起来是最符合逻辑的强制转换,但它在x84上“总是”安全吗 uint:假设在所有指针都为正的情况下,这将起作用?(就我的情况而言) long:假设这也是安全的,除非在x84上使用long创建新的IntPtr,否则不可能出现溢出吗 让我们假设我有一个很好的理由将其转换为上述类型之一,这样做背后的推理超出了这个问题的范围 我已经翻遍了我能找到的所有堆栈溢出问题,并查看了MS文档,但我担心我对该领域的知识不足严重限制了我找到答

问题

哪种类型转换最适合4字节IntPtr(特别是x84应用程序)

int:看起来是最符合逻辑的强制转换,但它在x84上“总是”安全吗

uint:假设在所有指针都为正的情况下,这将起作用?(就我的情况而言)

long:假设这也是安全的,除非在x84上使用long创建新的IntPtr,否则不可能出现溢出吗

让我们假设我有一个很好的理由将其转换为上述类型之一,这样做背后的推理超出了这个问题的范围

我已经翻遍了我能找到的所有堆栈溢出问题,并查看了MS文档,但我担心我对该领域的知识不足严重限制了我找到答案的能力


有一个方法
IntPtr.ToInt64()
IntPtr.ToInt32()
可以为您执行此操作。请注意,
IntPtr.ToInt32()
在64位平台上抛出一个
OverflowException
,因为实例太大或太小,无法表示为32位有符号整数。

经过许多同事的讨论,另一位高级开发人员建议我编写一个包装器,让环境自行决定需要做什么

测试之后,当使用Marshal.SizeOf(typeof(CPtr))时,它返回

  • x84上的4
  • x64上的8
这正是我们所期望的。但是,再加上不必投自己的额外奖励

public struct CPtr
{
    public IntPtr InnerPointer { get; }
    public static IntPtr Zero { get { return IntPtr.Zero; } }

    public CPtr(IntPtr innerPointer)
    {
        InnerPointer = innerPointer;
    }
    public CPtr(long o) : this(new IntPtr(o))
    { }
    public CPtr(uint o) : this(new IntPtr(o))
    { }
    public CPtr(int o) : this(new IntPtr(o))
    { }


    public static CPtr operator +(CPtr a, long b)
    {
        return new CPtr((long)a.InnerPointer + b);
    }
    public static CPtr operator +(CPtr a, IntPtr b) { return a + (long)b; }
    public static CPtr operator +(CPtr a, CPtr b) { return a + b.InnerPointer; }
    public static CPtr operator +(CPtr a, uint b) { return a + (long)b; }
    public static CPtr operator +(CPtr a, int b) { return a + (long)b; }

    public static CPtr operator -(CPtr a, long b) { return a + -b; }
    public static CPtr operator -(CPtr a, IntPtr b) { return a + -(long)b; }
    public static CPtr operator -(CPtr a, CPtr b) { return a - b.InnerPointer; }
    public static CPtr operator -(CPtr a, uint b) { return a + -b; }
    public static CPtr operator -(CPtr a, int b) { return a + -b; }

    public static implicit operator CPtr(IntPtr ptr) { return new CPtr(ptr); }
    public static implicit operator CPtr(long ptr) { return new CPtr(ptr); }
    public static implicit operator CPtr(uint ptr) { return new CPtr(ptr); }
    public static implicit operator CPtr(int ptr) { return new CPtr(ptr); }


    public static implicit operator IntPtr(CPtr ptr) { return ptr.InnerPointer; }
    public static implicit operator long (CPtr ptr) { return (long)ptr.InnerPointer; }
    public static implicit operator uint (CPtr ptr) { return (uint)ptr.InnerPointer; }
    public static implicit operator int (CPtr ptr) { return (int)ptr.InnerPointer; }
}

+1.我想补充一点,对于querent所关心的“除非您在x84[sic]上创建了一个带有long的新IntPtr,否则您不可能得到溢出吗?”的问题,答案是“是的,但前提是IntPtr超出了IntPtr在x86上的范围,因此,如果它来自程序,则不会出现问题”。坚持使用
Int64
转换可能会导致本机API不匹配,这可能会涉及就地显式转换,以修复以前对
ToInt64
的使用。问题稍微复杂一点,但因为THOP要求x86和签名的IntPtr,所以我支持它的第一个选项,使用ToInt32。如果有一天它的应用程序可以转换为x64或任何CPU,我会将ToInt32调用封装到一个静态方法中,并附带一个关于IntPtr大小为32位的调试检查