C# IntPtr加成

C# IntPtr加成,c#,.net,interop,intptr,C#,.net,Interop,Intptr,因此,从我所知道的,我发现的每一个IntPtr加法的托管示例都是错误的 例如: 我的想法是,如果IntPtr在32位系统上位于(或接近)int32.MaxValue,并且您添加了一个溢出int32的偏移量,那么这不是仍然是一个有效的内存地址吗(因为它在uint32中是有效的,并且在IntPtr中由负数表示) 我相信代码应该是这样的: public static IntPtr Offset(IntPtr src, int offset) { switch (IntPtr.Size) {

因此,从我所知道的,我发现的每一个IntPtr加法的托管示例都是错误的

例如:

我的想法是,如果IntPtr在32位系统上位于(或接近)int32.MaxValue,并且您添加了一个溢出int32的偏移量,那么这不是仍然是一个有效的内存地址吗(因为它在uint32中是有效的,并且在IntPtr中由负数表示)

我相信代码应该是这样的:

public static IntPtr Offset(IntPtr src, int offset)
{
    switch (IntPtr.Size) {
    case 4:
        return new IntPtr((int)((uint)src + offset));
    case 8:
        return new IntPtr((long)((ulong)src + offset));
    default:
        throw new NotSupportedException("Not supported");
    }
}
我疯了吗


是否有人有一个经过验证的IntPtr加法示例?

加法之前,IntPtr被强制转换为
uint
,然后应用偏移量。这将正常工作,但结果是
很长

据我所知,添加ulong和int是不可能的,因此64位指针部分是不正确的。事实上,它甚至没有编译。我真的想不出一个优雅的解决方案,但仅仅使用
long
可能是安全的。这是您可以使用的内存量的一半*,8 EB:)内存地址映射理论上可能是个问题


*:嗯,如果当前的.NET Framework实现不会阻止您在这之前执行long,当然:)

我认为关键是,如果您溢出了int,您仍然会得到适当的值。试试这个:

//-2147483645
Console.WriteLine( int.MaxValue + 4 );

//2147483651
Console.WriteLine( (uint)(int.MaxValue + 4) );

假定int.MaxValue为2147483647,将溢出的负数强制转换为uint实际上给出了正确的值。

.NET 4.0添加了一个新的静态方法IntPtr.Add(IntPtr指针,int偏移量)

在早期的.NET版本中,转换为整数的另一种方法是使用“不安全”代码块并将IntPtr转换为(字节*)。执行加法并将结果转换回IntPtr。编译器负责指针宽度的详细信息。:-)

例如:

  new IntPtr((byte *)pipe.Root + EventNameOffset)
或:


我刚刚看到.NETFramework4.0支持一种新的IntPtrs添加方法,有人使用Reflector查看MS在做什么吗?我没有安装4.0测试版的副本。愚蠢的是,我直到现在才尝试过这个(你必须在它周围添加未经检查的{}来编译它),但是你似乎是正确的。我确信.NET会抛出一个错误,但研究表明,只要在这里使用“unchecked”,这种方法就可以正常工作:啊,是的,我忘记了unchecked。我似乎记得,对于发布版本,默认值无论如何都是未经检查的——尽管如果编译器能够判断出某些内容将溢出(如我的示例!!doh!),那么它将阻止您。
  (IntPtr)((byte *)pipe.Root + EventNameOffset)