0

Question

Which cast is best for a 4byte IntPtr(strinctly an x84 application)

int : Looks like the most logical cast, but is it 'always' safe on x84?

uint : Suppose this will work given that all pointers are positive? (As far as i could find in my case)

long : Suppose this is also safe, except when you create a new IntPtr with a long on a x84, do you not possibly get an overflow?

Lets assume i have a good reason for casting to one of the above types, the reasoning behind doing so is out of scope of this question

I have dug through all stack overflow questions i could find, and had a look at MS documentation, but I'm afraid my lack of knowledge about this field is severely limiting my ability to find an answer.

Riaan Walters
  • 2,587
  • 2
  • 18
  • 30

2 Answers2

3

There is a method IntPtr.ToInt64() or IntPtr.ToInt32() that does it for you. Be aware of that IntPtr.ToInt32() throws a OverflowException on 64-bit plattform, because the instance is to large or too small to represent as a 32-bit signed integer.

CodeTherapist
  • 2,776
  • 14
  • 24
  • +1. I'd add that the answer to the querent's concern of "except when you create a new IntPtr with a long on a x84[sic], do you not possibly get an overflow?" is "yes, but only if the IntPtr is outside the range that an IntPtr will have on x86, so if it originated from the program it won't have an issue". – Jon Hanna Aug 06 '15 at 08:52
  • Sticking with `Int64` conversion can lead to native APIs mismatches, that then could involve in-place explicit casting to _fix_ previous use of `ToInt64`. The matter is little more complex, but because th OP asks for x86 and for signed IntPtr I would support its first option, using ToInt32. In the case its application could be someday converted to x64 or AnyCPU, I would enclose the ToInt32 call into a static method along with a Debug check about IntPtr size being 32bit. – Rubidium 37 Aug 06 '15 at 08:56
  • The IntPtr i ask for is indeed x86, but not specifically signed – Riaan Walters Aug 06 '15 at 12:17
-1

After some debate amost collegues, one of the other senior dev's suggested I write a wrapper and let the environment decide what it needs to do itself.

After testing this, when using Marshal.SizeOf(typeof(CPtr)) it returned

  • 4 on x84
  • 8 on x64

which is exactly as expected. but then with the added bonus of never having to cast yourself.

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; }
}
Riaan Walters
  • 2,587
  • 2
  • 18
  • 30