为什么我不能将两个IntPtr与<和>进行比较?

Pan*_*ama 8 c# pointers

我目前遇到不安全指针的问题,这似乎是一个编译器错误.

注意:问题不在于我使用指针和不安全的代码; 代码工作得很好.该问题与确认的编译器错误有关,该错误在某些情况下拒绝编译法律代码.如果您对该问题感兴趣,请访问我的其他问题

因为我的问题是指针变量的声明,所以我决定解决这个问题,然后使用IntPtr,并在需要时转换为实际的指针.

但是,我注意到我做不到这样的事情:

IntPtr a = something;
IntPtr b = somethingElse;
if (a > b) // ERROR. Can't do this
{
}
Run Code Online (Sandbox Code Playgroud)

><似乎运营商没有为被定义IntPtr.请注意,我确实可以比较两个实际指针.

IntPtr有一个.ToInt64()方法.但是,这会返回一个有符号值,在与之比较时可能会返回不正确的值,>并且<当涉及正值和负值时.

说实话,我真的不明白.ToInt64()对于返回有符号值的方法有什么用处,考虑到指针比较是无符号执行的,但这不是我的问题.

有人可能会争辩说,IntPtrs为不透明的手柄,这是毫无意义的,因此与比较><.但是,我会指出IntPtr有加法和减法的方法,这意味着实际上存在秩序概念IntPtr,因此>并且<确实有意义.

我想我可以将结果转换ToInt64()为a ulong然后进行比较,或者将其IntPtr转换为指针,然后进行比较,但它让我想到为什么不是><定义的IntPtr.

为什么我不能IntPtr直接比较两个?

xan*_*tos 6

IntPtr一直有点被忽视.直到.NET 4.0,甚至没有Add/ operator+Subtract/ operator-.

现在......如果你想比较两个指针,long如果它们是一个IntPtr或者ulong它们是什么,则将它们转换为UIntPtr.请注意,在Windows上,UIntPtr如果您使用带有该/3GB选项的32位程序,则只需要一个,因为否则32位程序只能使用较低的2gb地址空间,而对于64位程序,则远小于64位地址使用空格(此时为48位).

显然,如果你在.NET中进行内核编程,这会改变:-)(我在这里jocking,希望:-))

由于为什么IntPtr首选的原因UIntPtr:https://msdn.microsoft.com/en-us/library/system.intptr%28v=vs.110%29.aspx

IntPtr类型符合CLS,而UIntPtr类型则不符合.在公共语言运行库中仅使用IntPtr类型.提供UIntPtr类型主要是为了保持IntPtr类型的架构对称性.

有些语言没有区分有符号和无符号类型..NET想要支持它们.

通过使用完成一些测试

editbin /LARGEADDRESSAWARE myprogram.exe
Run Code Online (Sandbox Code Playgroud)

(我甚至能够崩溃我的图形适配器:-))

static void Main(string[] args)
{
    Console.WriteLine("Is 64 bits", Environment.Is64BitProcess);

    const int memory = 128 * 1024;

    var lst = new List<IntPtr>(16384); // More than necessary

    while (true)
    {
        Console.Write("{0} ", lst.Count);

        IntPtr ptr = Marshal.AllocCoTaskMem(memory);
        //IntPtr ptr = Marshal.AllocHGlobal(memory);
        lst.Add(ptr);

        if ((long)ptr < 0)
        {
            Console.WriteLine("\nptr #{0} ({1}, {2}) is < 0", lst.Count, ptr, IntPtrToUintPtr(ptr));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我能够使用32位程序(在64位操作系统上)分配近4 GB的内存(所以我有负面IntPtr)

这里,它是从铸造IntPtrUIntPtr

public static UIntPtr IntPtrToUintPtr(IntPtr ptr)
{
    if (IntPtr.Size == 4)
    {
        return unchecked((UIntPtr)(uint)(int)ptr);
    }

    return unchecked((UIntPtr)(ulong)(long)ptr);
}
Run Code Online (Sandbox Code Playgroud)

请注意,由于符号扩展如何工作,你不能简单地做(UIntPtr)(ulong)(long)ptr,因为在32位它会破坏.

但请注意,很少有程序在32位上支持> 2 gb ... http://blogs.msdn.com/b/oldnewthing/archive/2004/08/12/213468.aspx