【问题标题】:C# Safe IntPtr CastingC# 安全 IntPtr 铸造
【发布时间】:2015-08-06 08:41:17
【问题描述】:

问题

哪种转换最适合 4 字节的 IntPtr(严格来说是 x84 应用程序)

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

uint :假设所有指针都是正数,这将起作用? (据我所知)

long:假设这也是安全的,除非您在 x84 上创建一个带有 long 的新 IntPtr,否则您不会出现溢出吗?

假设我有充分的理由强制转换为上述类型之一,这样做的原因超出了这个问题的范围

我已经挖掘了所有我能找到的堆栈溢出问题,并查看了 MS 文档,但我担心我对这个领域的了解严重限制了我找到​​答案的能力。

【问题讨论】:

    标签: c# memory intptr


    【解决方案1】:

    有一种方法 IntPtr.ToInt64()IntPtr.ToInt32() 可以为您完成。请注意,IntPtr.ToInt32() 在 64 位平台上会抛出 OverflowException,因为实例太大或太小而无法表示为 32 位有符号整数。

    【讨论】:

    • +1。我想补充一点,回答了询问者的担忧“除非你在 x84 [原文如此] 上创建一个新的 IntPtr,否则你可能不会溢出吗?”是“是的,但前提是 IntPtr 超出了 IntPtr 在 x86 上的范围,因此如果它源自程序,则不会有问题”。
    • 坚持使用Int64 转换可能会导致本机API 不匹配,然后可能涉及就地显式转换以修复以前使用ToInt64。事情稍微复杂一点,但是因为 OP 要求 x86 和签名的 IntPtr,我会支持它的第一个选项,使用 ToInt32。如果有一天它的应用程序可能会转换为 x64 或 AnyCPU,我会将 ToInt32 调用与一个关于 IntPtr 大小为 32 位的调试检查一起包含在一个静态方法中。
    • 我要求的 IntPtr 确实是 x86,但没有特别签名
    【解决方案2】:

    在与大多数同事进行了一番辩论后,其他一位高级开发人员建议我编写一个包装器,让环境自行决定它需要做什么。

    经过测试,使用 Marshal.SizeOf(typeof(CPtr)) 时返回

    • x84 上的 4 个
    • 8 x64

    这完全符合预期。但随之而来的额外好处是永远不必自己施展。

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

    【讨论】:

      猜你喜欢
      • 2014-01-04
      • 1970-01-01
      • 2018-04-23
      • 1970-01-01
      • 1970-01-01
      • 2021-11-09
      • 2019-02-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多