开发者

IntPtr addition

So from what I can tell, every managed example of IntPtr addition I have found is WRONG.

For example: http://www.atalasoft.com/cs/blogs/stevehawley/archive/2006/10/16/10987.aspx

My thought being, that if IntPtr is at (o开发者_如何学运维r near) int32.MaxValue on a 32-bit system, and you add an offset which overflows int32, isn't that still a valid memory address (as it would be valid in uint32, and would be represented by a negative number in IntPtr)?!

I believe the code should be something like:

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

Am I crazy?

Does anyone have a tried and true IntPtr addition example?


I think the point is that if you overflow an int, you still get the appropriate value. Try this:

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

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

Given that int.MaxValue is 2147483647, casting the overflowed negative number to uint does in fact give the right value.


.NET 4.0 adds a new static method IntPtr.Add(IntPtr pointer, int offset).

On earlier .NET versions, an alternative method to converting to an integer is to use an 'unsafe' code block and cast the IntPtr to a (byte *). Perform your addition and turn the result back into an IntPtr. The compiler takes care of pointer width details. :-)

Example:

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

or:

  (IntPtr)((byte *)pipe.Root + EventNameOffset)


Before addition, the IntPtr is cast to a uint, then the offset is applied. This will work correctly, but the result is a long.

As far as I know, addition of ulong and an int is not possible, so the 64-bit pointer part is incorrect. Indeed it doesn't even compile. I can't really think of an elegant solution, but just using a long instead would probably be safe. That's half of a sh*tload of memory you could use*, 8 exabytes :) Memory address mapping could theoretically be a problem there though.

*: well, if the current .NET Framework implementation wouldn't stop you from doing so long before that of course :)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜